- Qual é a diferença entre "buffer" e o outro cache?
- Quando o Linux usa o cache de buffer em vez do cache de páginas?
- Por que podemos esperar que o cache de buffer seja maior ou menor?
1. Qual é a diferença entre "buffer" e o outro cache?
É seguro dizer que o cache de buffer é "armazenamento para blocos de disco brutos". Os blocos de disco usados pelo sistema de arquivos podem ser tão pequenos quanto 512 bytes. Isso difere do cache de páginas , usado para dados de arquivos.
O cache da página está vinculado ao tamanho da página da MMU, que normalmente é um mínimo de 4096 bytes. Isso é essencial para o acesso a arquivos mapeados no memmory [ 1 ] [2] e especificamente para carregar páginas de código individuais de programas em execução sob demanda. (Além disso, descarregar páginas quando algo mais precisa do espaço e elas não foram usadas recentemente).
2. Quando o Linux usa o cache de buffer em vez do cache de páginas?
No Linux moderno, seu cache de buffer provavelmente consiste em metadados do sistema de arquivos. Isso inclui o conteúdo do diretório.
Este uso do cache de buffer é dependente do sistema de arquivos, mas inclui o ext4 que é usado pelo sistema em questão.
Buffers
[in /proc/meminfo] are in-memory block I/O buffers. They are relatively short-lived. Prior to Linux kernel version 2.4, Linux had separate page and buffer caches. Since 2.4, the page and buffer cache are unified andBuffers
is raw disk blocks not represented in the page cache—i.e., not file data....
The buffer cache remains, however, as the kernel still needs to perform block I/O in terms of blocks, not pages. As most blocks represent file data, most of the buffer cache is represented by the page cache. But a small amount of block data isn't file backed—metadata and raw block I/O for example—and thus is solely represented by the buffer cache.
- Um par de Quora responde por Robert Love , última atualização em 2013.
Certain file systems, including ext3, ext4, and ocfs2, use the jbd or jbd2 layer to handle their physical block journalling, and this layer fundamentally uses the buffer cache, since it is concerned with controlling when specific file system blocks are allowed to ben written back to the hard drive.
Other file systems may not support file system blocks smaller than 4k. This may make it easier for them to use the page cache for their metadata blocks, although I don't know what happens if you try to mount a btrfs file system formatted with 4k blocks on an architecture such as Power which has 16k pages. I don't know if it will work, or blow up in a spectacular display of sparks. :-)
- Artigo de e-mail por Ted Tso , 2013
A primeira fonte já é citada no StackExchange, como a resposta mais autoritária para essa pergunta. linux - Qual é a coluna de buffers na saída de livre? . A segunda fonte tem detalhes técnicos mais específicos. Ambos os escritores são desenvolvedores Linux que trabalharam com o gerenciamento de memória do kernel Linux.
3. Por que podemos esperar que o cache de buffer seja maior ou menor?
Acontece que o tamanho do diário ext4 para o meu sistema de arquivos é de 128M. Então, isso explica porque 1) o cache de buffer pode se estabilizar em pouco mais de 128M; 2) cache de buffer não é dimensionado proporcionalmente com a maior quantidade de RAM no meu laptop.
Para provar que as anotações do diário usam o cache de buffer, simule um sistema de arquivos em RAM (tmpfs) e compare o uso máximo do buffer para diferentes tamanhos de diário.
# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=256
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size: 256M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
total used free shared buffers cache available
Mem: 7855 2521 4321 285 66 947 5105
Swap: 7995 0 7995
# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
total used free shared buffers cache available
Mem: 7855 2523 3872 551 237 1223 4835
Swap: 7995 0 7995
# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=16
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size: 16M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
total used free shared buffers cache available
Mem: 7855 2507 4337 285 66 943 5118
Swap: 7995 0 7995
# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
total used free shared buffers cache available
Mem: 7855 2509 4290 315 77 977 5086
Swap: 7995 0 7995
Como cheguei a olhar para o diário
Eu encontrei o e-mail primeiro e fiquei intrigado por enfatizar o write cache. Eu acharia surpreendente se dados "sujos", não-escritos conseguissem atingir 30% da RAM no meu sistema. sudo atop
mostra que, em um intervalo de 10 segundos, o sistema em questão grava consistentemente apenas 1 MB. O sistema de arquivos em questão seria capaz de acompanhar mais de 100 vezes essa taxa. (Está em uma unidade de disco rígido USB2, taxa de transferência máxima ~ 20MB / s).
Usar o blktrace ( btrace -w 10 /dev/sda
) confirma que os IOs que estão sendo armazenados em cache devem ser gravados, porque quase não há dados sendo lidos. Também que mysqld
é o único processo userspace fazendo IO.
Parei o serviço responsável pelas gravações (icinga2 escrevendo para o mysql) e verifiquei novamente. Eu vi "buffers" cair para menos de 20M - não tenho explicação para isso - e ficar lá. Reiniciar o gravador novamente mostra "buffers" aumentando em ~ 0.1M para cada intervalo de 10 segundos. Eu observei manter essa taxa consistentemente, subindo para 70M e acima.
A execução de echo 3 | sudo tee /proc/sys/vm/drop_caches
foi suficiente para reduzir novamente "buffers" para 4,5M. Isso prova que meu acúmulo de buffers é um cache "limpo", que o Linux pode descartar imediatamente quando necessário. Este sistema não está acumulando dados não escritos . ( drop_caches
não executa nenhum writeback e, portanto, não pode descartar páginas sujas. Se você quiser executar um teste que limpe o cache primeiro, use o comando sync
).
O diretório mysql inteiro é apenas 150M. Os buffers de acumulação devem representar blocos de metadados das gravações do mysql, mas me surpreendeu pensar que haveria tantos blocos de metadados para esses dados.