¿Descartar un archivo específico del caché del sistema de archivos de Linux?


23

Sé que puedo eliminar 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 le dice 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 pequeños archivos en caché para evitar búsquedas de disco, y no me importa almacenar en caché el archivo grande.


1
Con respecto a la recompensa, estoy específicamente interesado en la pregunta del título: soltar un archivo específico del caché (en lugar de evitar que llegue allí en primer lugar).
Gilles 'SO- deja de ser malvado'

Respuestas:


21

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 de caída por archivo .

extracto

Cong> Este es un parche borrador para implementar cachés de caída por archivo.

Interesante. Entonces, ¿puedo hacer esto desde fuera de un proceso? Soy un SysAdmin, por lo que mi POV es 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 en el rendimiento de esto cuando se ejecuta en un sistema ocupado? ¿Y qué nos compra este parche ya que me imagino que la máquina virtual ya debería estar cayendo cachés una vez que el sistema esté bajo presión?

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 al fs/drop_caches.cllamado drop_pagecache_file(struct file *filp). Esta función se puede acceder a través de la herramienta de interfaz, a fnctl.ctravés del comando F_DROP_CACHES. Este caso llama a esta función:

file_drop_caches(filp, arg);

Que maneja la caída 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 haya llegado al repositorio principal de código del kernel de Linux, por lo que esta opción parece 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.

Lo siguiente es un extracto de ese correo electrónico

Esta es una funcionalidad útil. ¿Aunque no está ya provisto POSIX_FADV_DONTNEED? Esta funcionalidad se agregó a GNU dd (8.11) hace un año .

Estos son los ejemplos de ese parche:
  • Aconsejar soltar caché para todo el archivo

     $ dd if=ifile iflag=nocache count=0
    
  • Asegúrese de soltar el caché para todo el archivo

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Caída de caché para parte del archivo

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Transmita datos utilizando solo el caché de lectura anticipada

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Probándolo

No era 100% positivo cómo probar esto, pero se me ocurrió el siguiente enfoque.

  1. hacer un archivo de 100 MB

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. rastrear accesos a archivos usando fatrace

    $ sudo fatrace | grep sample.txt
    
  3. ejecutar toppara que podamos monitorear el uso de memoria, nota cantidad libre.

    $ top
    
  4. Abra el archivo, observe la cantidad de memoria libre ahora. Tenga en cuenta la fatracedel archivo sample.txt.

    $ cat sample.txt > /dev/null
    
  5. suelte el archivo de la memoria, observe 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.txty 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 fatraceen la terminal # 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 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 fatraceen la terminal # 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 la terminal # 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Por lo tanto, parece que todo lo que consumió el archivo en RAM se libera.

Método potencial # 3 - python-fadvise

Gracias a un comentario de @frostchutz, hay otra herramienta, un script de Python, [pyadvise][4]que proporciona una interfaz mucho más simple que los ddmétodos anteriores . Este script hace uso de la misma posix_fadvise(2)interfaz.

Ejemplo
$ 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 pyadviseen lugar de dd:

$ pyadvise -d /home/saml/tst/162600/sample.txt

Noté una caída idéntica en la RAM que se consumía como antes cuando la usaba dd.


ddfunciona para mi. Terminé con chris-lamb.co.uk/projects/python-fadvise, que es lo mismo en un comando más obvio.
frostschutz

@frostschutz: muy bueno. No había oído hablar de esto hasta que Gilles preguntó si alguien sabía cómo hacerlo en el chat. python-fadvisees mucho más fácil, agregué un ejemplo que muestra dd.
slm

El enlace para el script de Python debe moverse al cuerpo principal de la pregunta. Los comentarios pueden desaparecer sin dejar rastro. En el peor de los casos, una edición permanecerá en la historia. Dicho esto, una búsqueda en Google lo encuentra fácilmente, por lo que no es un gran problema.
Faheem Mitha

Incluso parece funcionar sin sudo, por lo que cualquiera que pueda ver un archivo (incluso sin permiso de escritura) puede perder su caché, eso es ... interesante.
frostschutz

1
Hay os.posix_fadvise()en el libray estándar de Python ahora.
kawing-chiu


2

Puede abrir archivos individuales con el O_DIRECTindicador (ver man 2 open): lea la sección de NOTAS de esa página de manual cuidadosamente y considere si también desea / necesita O_SYNC.


1
Bueno, mi proceso es cat, y prefiero no reescribirlo. :) Esperaba una herramienta de línea de comandos o una /proc/sysperilla.
Jay Hacker

2
Peor que eso, sospecho que realmente quiere decir que está utilizando la redirección, por lo que su proceso es el shell. No sé de una manera por archivo para controlar esto aparte de la openbandera; de hecho, necesitarías escribir un programa para hacerlo. ( cat -uSólo se desactiva stdioel almacenamiento en búfer, no OS búfer.)
geekosaur

-2

Si desea forzar a un archivo a usar siempre O_SYNC, puede marcarlo así 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 sincrónicamente en el disco; esto es equivalente a la opción de montaje 'sincronización' aplicada a un subconjunto de los archivos.

O_SYNC obliga a que los datos + metadatos se escriban en los búferes de disco, pero aún pasa a través de la memoria 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 el archivo grande que se está agregando, la diferencia podría ser pequeña. Pero si el archivo grande se ha reescrito en lugares aleatorios, O_DIRECT será un gran éxito en el rendimiento, incluso teniendo en cuenta que tenerlo en caché podría desalojar de la caché algunos de los pequeños archivos de lectura.

Si tiene el ram para mantener todos los archivos pequeños allí, podría abordar el problema de la otra manera. Asegúrate de que los archivos pequeños estén siempre en RAM, entonces sugeriría copiarlos en tmpfs :

tmpfs pone todo en las cachés internas del núcleo y crece y se reduce para acomodar los archivos que contiene


chattr +Sno es lo mismo que O_DIRECT, es lo mismo que O_SYNC. O_DIRECThace que las lecturas no se almacenen en caché (de eso se trata esta pregunta) y las escrituras no se almacenan en el búfer, sin garantía. O_SYNChace que solo las escrituras no sean almacenadas.
Gilles 'SO- deja de ser malvado'

@Gilles tiene razón, leí la pregunta y pensé en vaciar datos en el disco como lo había hecho antes. Y hay otra sutil, pero importante en este caso, la diferencia entre O_DIRECT y O_SYNC, O_DIRECT omite el caché de la página, pero O_SYNC no, obliga a que los datos (y metadatos) se vacíen al disco, pero pasan a través del caché de la página y se mantiene allí para acelerar las lecturas. ¿Debo cambiar O_DIRECT por O_SYNC en mi respuesta para no dejar que se quede con una afirmación incorrecta?
Jorge Nerín

Esta pregunta se refiere a mantener un archivo grande que se ha escrito fuera de la caché. Creo que abrirlo con O_DIRECT sería perjudicial para el rendimiento, y si el archivo grande solo se agrega, la diferencia podría ser pequeña. Pero si el archivo grande se ha reescrito en lugares aleatorios, O_DIRECT será un gran éxito en el rendimiento, incluso teniendo en cuenta que podría expulsar de la memoria caché algunos de los archivos de lectura pequeños.
Jorge Nerín

Cambiar O_DIRECTa O_SYNCharía que su respuesta sea internamente consistente, pero aún así errónea teniendo en cuenta la pregunta.
Gilles 'SO- deja de ser malvado'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.