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 segmento de e-mail intitulado: Re: [RFC Patch] fs: implemente caches de descarte por arquivo .
excerto
Cong> Este é um patch de rascunho da implementação de caches descartáveis por arquivo.
Interessante. Então, posso fazer isso de fora de um processo? Como sou um SysAdmin, meu POV é perceber, encontrar e corrigir problemas de desempenho quando o sistema está sob pressão.
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.
Como posso saber quanto cache é usado por um arquivo? E qual é o impacto no desempenho disso quando executado em um sistema ocupado? E o que esse patch nos compra desde que eu acho que a VM já deveria estar deixando caches quando o sistema fica sob pressão de memória ...
Cong> Abaixo está um pequeno caso de teste para este patch:
O encadeamento inclui um testcase e o patch real em vários arquivos no 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 eliminação de todos os caches associados ao arquivo especificado. 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 já tenha chegado ao repositório principal de códigos do kernel do Linux; portanto, essa opção parece estar disponível apenas se você estiver disposto a recompilar o kernel do Linux.
Método potencial # 2 - Usando dd
Nesse mesmo segmento, outro usuário menciona uma metodologia completamente diferente que utiliza dd
.
A seguir, trecho desse email
Essa é uma funcionalidade útil. Embora já não seja fornecido
POSIX_FADV_DONTNEED
? Esta funcionalidade foi adicionada ao GNU dd (8.11) há um ano .
Aqui estão os exemplos desse patch:
Aconselhar a descartar o cache do arquivo inteiro
$ dd if=ifile iflag=nocache count=0
Garanta que o cache seja descartado para o arquivo inteiro
$ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
Soltar cache para parte do arquivo
$ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
Transmita dados usando apenas o cache de leitura antecipada
$ dd if=ifile of=ofile iflag=nocache oflag=nocache
Testando
Eu não estava 100% positivo em como testar isso, mas criei a seguinte abordagem.
faça um arquivo de 100MB
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
arquivo de rastreio acessa usando fatrace
$ sudo fatrace | grep sample.txt
execute top
para que possamos monitorar o uso da memória, observe a quantidade grátis.
$ top
abra o arquivo, observe a quantidade de memória livre agora. Observe fatrace
o arquivo sample.txt
.
$ cat sample.txt > /dev/null
solte 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 observe 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 do fatrace
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
Observe a saída do fatrace
terminal # 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Observe a RAM no terminal # 3:
KiB Mem: 7968336 total, 6908364 used, 1059972 free, 267364 buffers
Portanto, parece que tudo o que foi consumido pelo arquivo na RAM é liberado.
Método potencial # 3 - python-fadvise
Graças a um comentário de @frostchutz, existe outra ferramenta, um script Python, nomeado [pyadvise][4]
que fornece uma interface muito mais simples do que os dd
métodos acima . Este script utiliza a mesma posix_fadvise(2)
interface.
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 usarmos pyadvise
no lugar de dd
:
$ pyadvise -d /home/saml/tst/162600/sample.txt
Notei uma queda idêntica na RAM sendo consumida como antes quando eu usei dd
.