Descarta um arquivo específico do cache do sistema de arquivos do Linux?

23

Eu sei que posso largar tudo do Linux cache do sistema de arquivos , mas existe uma maneira de descartar apenas um arquivo específico? Ou impedir que um arquivo seja armazenado em cache? Ou diga a um processo para não armazenar em cache nenhum arquivo escrito por ele?

Eu tenho um processo que lê muitos arquivos pequenos e grava um arquivo grande. Eu quero manter os pequenos arquivos em cache para evitar buscas em disco, e não me importo com o cache do arquivo grande.

    
por Jay Hacker 20.04.2012 / 00:12

4 respostas

20

Método Potencial 1 - F_DROP_CACHES

Eu encontrei um método a partir de 2012 que discute um patch proposto para o kernel Linux neste tópico de e-mail intitulado: [RFC Patch] fs: implemente caches de lançamento por arquivo .

trecho

Cong> This is a draft patch of implementing per-file drop caches.

Interesting. So can I do this from outside a process? I'm a SysAdmin, so my POV is from noticing, finding and fixing performance problems when the system is under pressure.

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.

How can I tell how much cache is used by a file? And what is the performance impact of this when run on a busy system? And what does this patch buy us since I figure the VM should already be dropping caches once the system comes under mem pressure...

Cong> Below is small test case for this patch:

O encadeamento inclui um testcase e o patch real para vários arquivos dentro do kernel do Linux, o que adiciona uma função adicional ao fs/drop_caches.c chamado drop_pagecache_file(struct file *filp) . Esta função é então acessível através da ferramenta frontend, fnctl.c através do comando F_DROP_CACHES . Este caso chama esta função:

file_drop_caches(filp, arg);

Que lida com a queda de todos os caches associados ao arquivo fornecido. Do arquivo include/linux/mm.h :

void file_drop_caches(struct file *filp, unsigned long which);
Então, isso pode ser usado?

Não encontrei nenhuma evidência de que esse patch tenha entrado no repositório principal de código do kernel do Linux, portanto, esta opção parece estar disponível apenas se você estiver disposto a recompilar o kernel do Linux.

Método Potencial 2 - Usando o dd

Nesse mesmo segmento, outro usuário menciona uma metodologia completamente diferente que faz uso de dd .

O seguinte é um trecho desse e-mail

This is useful functionality. Though isn't it already provided with POSIX_FADV_DONTNEED? This functionality was added to GNU dd (8.11) a year ago.

Here are the examples from that patch:
  • Advise to drop cache for whole file

     $ dd if=ifile iflag=nocache count=0
    
  • Ensure drop cache for the whole file

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Drop cache for part of file

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Stream data using just the read-ahead cache

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Teste

Eu não tinha 100% de certeza sobre como testar isso, mas desenvolvi a seguinte abordagem.

  1. crie um arquivo de 100MB

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. acessa arquivos de rastreio usando fatrace

    $ sudo fatrace | grep sample.txt
    
  3. execute top para que possamos monitorar o uso da memória, valor da nota livre.

    $ top
    
  4. abra o arquivo, anote a quantidade de memória livre agora. Observe o fatrace do arquivo sample.txt .

    $ cat sample.txt > /dev/null
    
  5. elimine o arquivo da memória, observe a quantidade de memória livre agora. Observe a saída de fatrace .

    $ sudo dd of=/home/saml/tst/162600/sample.txt \
        oflag=nocache conv=notrunc,fdatasync count=0
    

Exemplo

No 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
No terminal 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
No terminal 3:
$ sudo fatrace | grep sample.txt
Agora abra o arquivo sample.txt e anote a quantidade de RAM. No terminal 1.
$ cat sample.txt > /dev/null
No terminal 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Observe a saída de fatrace no 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
Agora remova o arquivo da RAM, no terminal # 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Anote a saída de fatrace no terminal # 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Anote a RAM no terminal # 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Assim, parece que tudo o que foi consumido pelo arquivo na RAM é liberado.

Método Potencial nº 3 - python-fadvise

Graças a um comentário de @frostchutz, há outra ferramenta, um script Python, chamado [pyadvise][4] , que fornece uma interface muito mais simples do que os métodos dd acima. Este script faz uso da mesma interface posix_fadvise(2) .

Exemplo
$ 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

E se repetirmos o teste acima e usar pyadvise no lugar de dd :

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

Eu notei uma queda idêntica na RAM sendo consumida como antes, quando usei dd .

    
por 18.10.2014 / 02:37
3

Expandindo a resposta do @ geekosaur, você pode forçar o uso de O_DIRECT usando LD_PRELOAD e o programa aqui: link

Esse código força O_DIRECT para todos os arquivos. No entanto, basta adicionar mais alguma lógica strncmp em __do_wrap_open e você pode aplicar seletivamente O_DIRECT.

Aviso: Eu não testei isso.

    
por 18.10.2014 / 00:44
2

Você pode abrir arquivos individuais com o sinalizador O_DIRECT (consulte man 2 open ) - leia atentamente a seção NOTES dessa página do manual e considere se também deseja / precisa O_SYNC .

    
por 20.04.2012 / 00:17
-2

Se você quiser forçar um arquivo a sempre usar O_SYNC, você pode marcá-lo dessa forma nos atributos estendidos com chattr +S $file :

homem chattr:

When a file with the 'S' attribute set is modified, the changes are written synchronously on the disk; this is equivalent to the 'sync' mount option applied to a subset of the files.

O_SYNC força os dados + metadados a serem gravados nos buffers de disco, mas ainda passa pelo cache de páginas. O_DIRECT ignora o cache da página.

Mas lembre-se de que abri-lo com O_DIRECT seria prejudicial para o desempenho, se o arquivo grande que está sendo anexado a diferença pode ser pequeno. Mas se o arquivo grande for reescrito em lugares aleatórios, O_DIRECT será um grande sucesso no desempenho, mesmo levando em conta que tê-lo em cache poderia despejar do cache alguns dos pequenos arquivos de leitura.

Se você tiver o RAM para manter todos os arquivos pequenos lá, você poderia abordar o problema de outra maneira. Certifique-se de que os arquivos pequenos estão sempre em memória RAM, então sugiro copiá-los para tmpfs :

tmpfs puts everything into the kernel internal caches and grows and shrinks to accommodate the files it contains

    
por 18.10.2014 / 17:49