
Sé que puedoelimine todo del caché del sistema de archivos de Linux, pero ¿hay alguna manera de eliminar solo un archivo específico? ¿O evitar que un archivo se almacene en caché? ¿O decirle a un proceso que no guarde en caché los archivos que escribe?
Tengo un proceso que lee muchos archivos pequeños y escribe un archivo grande. Quiero mantener los archivos pequeños en caché para evitar búsquedas en el disco y no me importa almacenar en caché el archivo grande.
Respuesta1
Método potencial n.º 1: F_DROP_CACHES
Encontré un método de 2012 que analiza un parche propuesto para el kernel de Linux en este hilo de correo titulado:Re: [Parche RFC] fs: implementar cachés por archivo.
extractoCong> Este es un borrador de parche para implementar cachés de caída por archivo.
Interesante. Entonces, ¿puedo hacer esto desde fuera de un proceso? Soy SysAdmin, por lo que mi punto de vista consiste en notar, encontrar y solucionar problemas de rendimiento cuando el sistema está bajo presión.
Cong> It introduces a new fcntl command F_DROP_CACHES to drop Cong> file caches of a specific file. The reason is that currently Cong> we only have a system-wide drop caches interface, it could Cong> cause system-wide performance down if we drop all page caches Cong> when we actually want to drop the caches of some huge file.
¿Cómo puedo saber cuánto caché utiliza un archivo? ¿Y cuál es el impacto de esto en el rendimiento cuando se ejecuta en un sistema ocupado? ¿Y qué nos compra este parche? Ya que me imagino que la VM ya debería estar eliminando cachés una vez que el sistema esté bajo presión de memoria...
Cong> A continuación se muestra un pequeño caso de prueba para este parche:
El hilo incluye un caso de prueba y el parche real para varios archivos dentro del kernel de Linux que agrega una función adicional a fs/drop_caches.c
call drop_pagecache_file(struct file *filp)
. Luego se puede acceder a esta función a través de la herramienta de interfaz, fnctl.c
mediante el comando F_DROP_CACHES
. Este caso llama a esta función:
file_drop_caches(filp, arg);
Que maneja la eliminación de todos los cachés asociados con el archivo dado. Del archivo include/linux/mm.h
:
void file_drop_caches(struct file *filp, unsigned long which);
¿Entonces esto se puede usar?
No encontré evidencia de que este parche alguna vez haya llegado al repositorio principal de código del kernel de Linux, por lo que esta opción parecería estar disponible, solo si está dispuesto a recompilar el kernel de Linux usted mismo.
Método potencial n.º 2: uso de dd
En ese mismo hilo, otro usuario menciona una metodología completamente diferente que utiliza dd
.
ProbandoloEsta es una funcionalidad útil. ¿Aunque no está ya provisto
Aquí están los ejemplos de ese parche:POSIX_FADV_DONTNEED
? Esta funcionalidad fue agregada aGNU dd (8.11) hace un año.
Aconsejamos eliminar el caché de todo el archivo
$ dd if=ifile iflag=nocache count=0
Asegúrese de descartar caché para todo el archivo
$ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
Eliminar caché de parte del archivo
$ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
Transmita datos usando solo el caché de lectura anticipada
$ dd if=ifile of=ofile iflag=nocache oflag=nocache
No estaba 100% seguro de cómo probar esto, pero se me ocurrió el siguiente enfoque.
hacer un archivo de 100 MB
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
rastrear accesos a archivos usando
fatrace
$ sudo fatrace | grep sample.txt
ejecutar
top
para que podamos monitorear el uso de la memoria, anotar la cantidad libre.$ top
Abra el archivo y observe la cantidad de memoria libre ahora. Tenga en cuenta la
fatrace
del archivosample.txt
.$ cat sample.txt > /dev/null
suelte el archivo de la memoria, anote la cantidad de memoria libre ahora. Tenga en cuenta la salida de
fatrace
.$ sudo dd of=/home/saml/tst/162600/sample.txt \ oflag=nocache conv=notrunc,fdatasync count=0
Ejemplo
En la terminal #1:$ dd if=/dev/urandom of=sample.txt bs=100M count=1
1+0 records in
1+0 records out
104857600 bytes (105 MB) copied, 7.37996 s, 14.2 MB/s
$ ls -l sample.txt
-rw-rw-r--. 1 saml saml 104857600 Oct 17 22:54 sample.txt
En la terminal #2:
$ top
...
KiB Mem: 7968336 total, 6900956 used, 1067380 free, 267080 buffers
...
En la terminal 3:
$ sudo fatrace | grep sample.txt
Ahora abra el archivo sample.txt
y observe la cantidad de RAM. En la terminal #1.
$ cat sample.txt > /dev/null
En la terminal #2:
KiB Mem: 7968336 total, 7011896 used, 956440 free, 267336 buffers
Observe la salida de fatrace
en la terminal n.° 3:
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): RC /home/saml/tst/162600/sample.txt
Ahora elimine el archivo de la RAM, en la terminal 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
oflag=nocache conv=notrunc,fdatasync count=0
Tenga en cuenta la salida de fatrace
en la terminal n.° 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Tenga en cuenta la RAM en el terminal n.° 3:
KiB Mem: 7968336 total, 6908364 used, 1059972 free, 267364 buffers
Entonces parecería que todo lo que consumió el archivo en la RAM se libera.
Método potencial n.° 3: python-fadvise
Gracias a un comentario de @frostchutz, hay otra herramienta, un script de Python, [pyadvise][4]
cuyo nombre proporciona una interfaz mucho más simple que los dd
métodos anteriores. Este script utiliza la misma posix_fadvise(2)
interfaz.
$ sudo pyadvise --help
Usage:
pyadvise [options] [FILE]..
Options:
-h, --help show this help message and exit
-w, --willneed The specified files will be accessed in the near future
-s, --sequential The application expects to access the specified files
sequentially (with lower offsets read before higher ones)
-d, --dontneed The specified files will not be accessed in the near
future
-r, --random The specified files will be accessed in random order
-o, --noreuse The specified files will be accessed only once. Under
Linux, this operation is a no-op; see contrib/copyfileobj-
fadvise.py in the python-fadvise source tree for an
example on how to achieve approximately the same effect
-n, --normal Indicates that the application has no advice to give about
its access pattern for the specified files. If no advice
is given for an open file, this is the default assumption
-v, --verbose Explain what is being done
Y si repetimos la prueba anterior y la usamos pyadvise
en lugar de dd
:
$ pyadvise -d /home/saml/tst/162600/sample.txt
Noté una caída idéntica en el consumo de RAM que antes cuando usaba dd
.
Respuesta2
Ampliando la respuesta de @geekosaur, puedes forzar el uso O_DIRECT
usando LD_PRELOAD y el programa aquí:http://arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html
Ese código obliga O_DIRECT
a todos los archivos. Sin embargo, simplemente agregando más lógica strncmp __do_wrap_open
puede aplicar O_DIRECT de forma selectiva.
Descargo de responsabilidad: no he probado esto.
Respuesta3
Puede abrir archivos individuales con la O_DIRECT
bandera (ver man 2 open
): lea elNOTASsección de esa página de manual cuidadosamente y considere si también desea/necesita O_SYNC
.
Respuesta4
Si desea forzar que un archivo use siempre O_SYNC, puede marcarlo como tal en los atributos extendidos con chattr +S $file
:
hombre chattr:
Cuando se modifica un archivo con el conjunto de atributos 'S', los cambios se escriben de forma sincrónica en el disco; esto es equivalente a la opción de montaje 'sincronizar' aplicada a un subconjunto de archivos.
O_SYNC fuerza que los datos + metadatos se escriban en los búferes del disco, pero aún así pasan a través del caché de la página. O_DIRECT omite el caché de la página.
Pero tenga en cuenta que abrirlo con O_DIRECT sería perjudicial para el rendimiento; si simplemente se agrega el archivo grande, la diferencia podría ser pequeña. Pero si el archivo grande se ha reescrito en lugares aleatorios, O_DIRECT será un gran impacto en el rendimiento, incluso teniendo en cuenta que tenerlo en caché podría posiblemente expulsar del caché algunos de los archivos pequeños leídos.
Si tiene la memoria RAM para guardar todos los archivos pequeños allí, puede abordar el problema de otra manera. Asegúrese de que los archivos pequeños estén siempre en la RAM, luego sugeriría copiarlos atmpfs:
tmpfs coloca todo en las cachés internas del kernel y crece y se reduce para acomodar los archivos que contiene