desenv-web-rp.com

Posso configurar meu sistema Linux para um cache mais agressivo do sistema de arquivos?

Não estou preocupado com o uso de RAM (como tenho o suficiente) nem com a perda de dados em caso de desligamento acidental (como minha energia é suportada, o sistema é confiável e os dados não são críticos), mas eu faço muito processamento de arquivos e poderia usar algum aumento de desempenho.

É por isso que eu gostaria de configurar o sistema para usar mais RAM para cache de leitura e gravação do sistema de arquivos, para pré-buscar arquivos de forma agressiva (por exemplo, leia antecipadamente todo o arquivo acessado por um aplicativo) o arquivo é do mesmo tamanho ou, pelo menos, lê-se antecipadamente uma grande parte dele) e libera os buffers de gravação com menos frequência.Como conseguir isso (pode ser possível)?

Eu uso sistemas de arquivos ext3 e ntfs (uso muito ntfs!) Com o XUbuntu 11.10 x86.

124
Ivan

Melhorar o desempenho do cache de disco em geral é mais do que apenas aumentar o tamanho do cache do sistema de arquivos, a menos que o sistema todo se encaixe RAM; nesse caso, você deve usar RAM drive (tmpfs é boa porque permite voltar ao disco se você precisar do RAM em alguns casos)) para armazenamento em tempo de execução (e talvez um initrd script para copiar o sistema do armazenamento para a unidade RAM na inicialização).

Você não disse se o seu dispositivo de armazenamento é SSD ou HDD. Aqui está o que eu descobri que funciona para mim (no meu caso sda é um HDD montado em /home e sdb são SSD montados em /).

Primeiro otimize a parte carregar coisas do armazenamento para o cache:

Aqui está minha configuração para o HDD (verifique se o AHCI + NCQ está ativado no BIOS se você tiver alternado):

echo cfq > /sys/block/sda/queue/scheduler
echo 10000 > /sys/block/sda/queue/iosched/fifo_expire_async
echo 250 > /sys/block/sda/queue/iosched/fifo_expire_sync
echo 80 > /sys/block/sda/queue/iosched/slice_async
echo 1 > /sys/block/sda/queue/iosched/low_latency
echo 6 > /sys/block/sda/queue/iosched/quantum
echo 5 > /sys/block/sda/queue/iosched/slice_async_rq
echo 3 > /sys/block/sda/queue/iosched/slice_idle
echo 100 > /sys/block/sda/queue/iosched/slice_sync
hdparm -q -M 254 /dev/sda

Vale ressaltar que o caso do disco rígido é alto fifo_expire_async (geralmente escreve) e longo slice_sync para permitir que um único processo obtenha alto rendimento (defina slice_sync para diminuir o número se você encontrar situações em que vários processos aguardam alguns dados do disco em paralelo). O slice_idle é sempre um compromisso para os HDDs, mas defini-lo em algum lugar no intervalo de 3 a 20 deve ser bom, dependendo do uso e do firmware do disco. Prefiro segmentar valores baixos, mas defini-lo muito baixo destruirá sua taxa de transferência. A configuração quantum parece afetar muito a taxa de transferência, mas tente manter o mais baixo possível para manter a latência em nível sensato. Definir quantum muito baixo destruirá a taxa de transferência. Os valores no intervalo de 3 a 8 parecem funcionar bem com os HDDs. A pior latência para uma leitura é (quantum * slice_sync) + (slice_async_rq * slice_async) ms se eu entendi o comportamento do kernel corretamente. O assíncrono é usado principalmente por gravações e, como você deseja adiar a gravação no disco, defina os dois slice_async_rq e slice_async para números muito baixos. No entanto, a configuração slice_async_rq Um valor muito baixo pode interromper as leituras, porque as gravações não podem ser atrasadas após as leituras mais. Minha configuração tentará gravar dados no disco no máximo 10 segundos depois que os dados foram passados ​​para o kernel, mas como você pode tolerar a perda de dados na perda de energia também defina fifo_expire_async para 3600000 para dizer que 1 hora é aceitável para o atraso no disco. Apenas mantenha o slice_async baixo, no entanto, porque, caso contrário, você poderá obter alta latência de leitura.

O comando hdparm é necessário para impedir que o AAM diminua grande parte do desempenho permitido pelo AHCI + NCQ. Se o seu disco emitir muito ruído, pule-o.

Aqui está minha configuração para SSD (Intel 320 series):

echo cfq > /sys/block/sdb/queue/scheduler
echo 1 > /sys/block/sdb/queue/iosched/back_seek_penalty
echo 10000 > /sys/block/sdb/queue/iosched/fifo_expire_async
echo 20 > /sys/block/sdb/queue/iosched/fifo_expire_sync
echo 1 > /sys/block/sdb/queue/iosched/low_latency
echo 6 > /sys/block/sdb/queue/iosched/quantum
echo 2 > /sys/block/sdb/queue/iosched/slice_async
echo 10 > /sys/block/sdb/queue/iosched/slice_async_rq
echo 1 > /sys/block/sdb/queue/iosched/slice_idle
echo 20 > /sys/block/sdb/queue/iosched/slice_sync

Aqui vale a pena observar os valores baixos para diferentes configurações de fatia. A configuração mais importante para um SSD é slice_idle que deve ser definido como 0-1. A configuração para zero move todas as decisões de pedido para o NCQ nativo, enquanto a configuração para 1 permite que o kernel solicite solicitações (mas se o NCQ estiver ativo, o hardware poderá substituir parcialmente a solicitação do kernel). Teste os dois valores para ver se você consegue ver a diferença. Para a série Intel 320, parece que a configuração slide_idle para 0 fornece a melhor taxa de transferência, mas a define como 1 fornece a melhor (mais baixa) latência geral.

Para obter mais informações sobre esses ajustáveis, consulte https://www.kernel.org/doc/Documentation/block/cfq-iosched.txt .

Agora que configuramos o kernel para carregar coisas do disco para o cache com desempenho razoável, é hora de ajustar o comportamento do cache:

De acordo com os benchmarks que eu fiz, eu não me incomodaria em definir a leitura antecipada via blockdev. As configurações padrão do kernel estão bem.

Defina o sistema para preferir trocar dados do arquivo pelo código do aplicativo (isso não importa se você possui o suficiente RAM para manter todo sistema de arquivos e todo o código do aplicativo e toda a memória virtual alocada pelos aplicativos na RAM). Isso reduz a latência para trocar entre aplicativos diferentes por latência para acessar arquivos grandes a partir de um único aplicativo:

echo 15 > /proc/sys/vm/swappiness

Se você preferir manter os aplicativos quase sempre em RAM, você pode definir isso como 1. Se você definir como zero, o kernel não será trocado, a menos que seja absolutamente necessário para evitar o OOM). limitado e trabalhando com arquivos grandes (por exemplo, edição de vídeo em HD), pode fazer sentido definir esse valor próximo a 100.

Hoje em dia (2017) prefiro não ter nenhuma troca, se você tiver RAM suficiente. Não ter troca normalmente perde 200-1000 MB de RAM em uma máquina desktop de longa duração. Estou disposto a sacrificar muito para evitar a pior latência do cenário) (trocar o código do aplicativo quando RAM está cheio). Na prática, isso significa que prefiro o OOM Killer à troca. Se você permitir/precisar de troca, talvez queira aumentar /proc/sys/vm/watermark_scale_factor também, para evitar alguma latência. Eu sugeriria valores entre 100 e 500. Você pode considerar essa configuração como negociando o uso da CPU por uma menor latência de troca. O padrão é 10 e o máximo possível é 1000. Um valor mais alto deve (de acordo com documentação do kernel ) resultar em maior uso da CPU para processos kswapd e menor latência geral de troca.

Em seguida, diga ao kernel para preferir manter a hierarquia de diretórios na memória sobre o conteúdo do arquivo, caso alguns RAM precisem ser liberados (novamente, se tudo couber na RAM, essa configuração não faz nada):

echo 10 > /proc/sys/vm/vfs_cache_pressure

Configuração vfs_cache_pressure para valor baixo faz sentido porque, na maioria dos casos, o kernel precisa conhecer a estrutura de diretórios antes de poder usar o conteúdo do arquivo no cache e liberá-lo muito cedo fará com que o cache de arquivos seja praticamente inútil. Considere descer até 1 com essa configuração se você tiver muitos arquivos pequenos (meu sistema tem fotos com cerca de 150 mil e 10 megapixels e conta como sistema "muitos arquivos pequenos"). Nunca defina como zero ou a estrutura de diretórios será sempre mantida na memória, mesmo que o sistema esteja ficando sem memória. Definir esse valor como grande é sensato apenas se você tiver apenas alguns arquivos grandes que estão sendo relidos constantemente (novamente, edição de vídeo em HD sem suficiente RAM seria um exemplo de caso). A documentação diz que "aumentar vfs_cache_pressure significativamente além de 100 pode ter um impacto negativo no desempenho".

Exceção: se você tiver uma quantidade realmente grande de arquivos e diretórios e você raramente toca/lê/lista todos os arquivos configurando vfs_cache_pressure maior que 100 pode ser sábio. Isso só se aplica se você não tiver o suficiente RAM e não puder manter toda a estrutura de diretórios em RAM e ainda tiver o suficiente RAM para processos e cache de arquivos normais (por exemplo, servidor de arquivos para toda a empresa com muito conteúdo de arquivamento) .Se você acha que precisa aumentar vfs_cache_pressure acima de 100 você está executando sem RAM suficiente. Aumentando vfs_cache_pressure pode ajudar, mas a única solução real é obter mais RAM. Tendo vfs_cache_pressure definido como número alto sacrifica o desempenho médio por ter um desempenho geral mais estável (ou seja, você pode evitar um comportamento muito ruim no pior dos casos, mas precisa lidar com um desempenho geral pior).

Por fim, diga ao kernel para usar até 99% do RAM como cache para gravações e instrua o kernel a usar até 50% de RAM antes de abrandar o processo que está gravando (padrão para dirty_background_ratio é 10). Aviso: eu pessoalmente não faria isso, mas você afirmou ter o suficiente RAM e está disposto a perder os dados.

echo 99 > /proc/sys/vm/dirty_ratio
echo 50 > /proc/sys/vm/dirty_background_ratio

E diga que 1h de atraso de gravação é bom para até start escrever coisas no disco (novamente, eu não faria isso):

echo 360000 > /proc/sys/vm/dirty_expire_centisecs
echo 360000 > /proc/sys/vm/dirty_writeback_centisecs

Para obter mais informações sobre esses ajustes, consulte https://www.kernel.org/doc/Documentation/sysctl/vm.txt

Se você colocar tudo isso para /etc/rc.local e inclua o seguinte no final, tudo ficará em cache assim que possível após a inicialização (faça isso apenas se o seu sistema de arquivos realmente se encaixar na RAM):

(Nice find / -type f -and -not -path '/sys/*' -and -not -path '/proc/*' -print0 2>/dev/null | Nice ionice -c 3 wc -l --files0-from - > /dev/null)&

Ou uma alternativa um pouco mais simples, que pode funcionar melhor (somente cache /home e /usr, faça isso apenas se o seu /home e /usr realmente cabe na RAM):

(Nice find /home /usr -type f -print0 | Nice ionice -c 3 wc -l --files0-from - > /dev/null)&
113
Mikko Rantalainen

Em primeiro lugar, NÃO recomendo que você continue usando o NTFS, pois a implementação do NTFS no Linux seria um problema de desempenho e segurança a qualquer momento.

Há várias coisas que você pode fazer:

  • use alguns fs mais recentes, como ext4 ou btrfs
  • tente alterar seu agendador io, por exemplo bfq
  • desativar troca
  • use algum pré-carregador automático como preload
  • use algo como systemd para pré-carregar durante a inicialização
  • ... e algo mais

Talvez você queira experimentá-lo :-)

16
Felix Yan

Leia adiante:

Em sistemas de 32 bits:

blockdev --setra 8388607 /dev/sda

Em sistemas de 64 bits:

blockdev --setra 4294967295 /dev/sda

Escreva atrás do cache:

echo 100 > /proc/sys/vm/dirty_ratio

Isso utilizará até 100% de sua memória livre como cache de gravação.

Ou você pode usar todos os recursos e usar tmpfs. Isso só é relevante se você tiver RAM suficiente. Coloque isso em /etc/fstab. Substitua 100G pela quantidade de RAM física.

tmpfs /mnt/tmpfs tmpfs size=100G,rw,nosuid,nodev 0 0

Então:

mkdir /mnt/tmpfs; mount -a

Então use/mnt/tmpfs.

8
Ole Tange

Você pode definir o tamanho da leitura antecipada com blockdev --setra sectors /dev/sda1, onde setores é o tamanho que você deseja em setores de 512 bytes.

6
psusi

Minha configuração matadora é muito simples e muito eficaz:

echo "2000" > /proc/sys/vm/vfs_cache_pressure

A explicação de documentação do kernel :

vfs_cache_pressure

Controla a tendência do kernel de recuperar a memória usada para armazenar em cache objetos de diretório e inode.

No valor padrão de vfs_cache_pressure = 100, o kernel tentará recuperar dentries e inodes a uma taxa "razoável" em relação à recuperação de pagecache e swapcache. Diminuir vfs_cache_pressure faz com que o kernel prefira reter caches de dentry e inode. Quando vfs_cache_pressure = 0, o kernel nunca recuperará dentries e inodes devido à pressão da memória e isso pode facilmente levar a condições de falta de memória. Aumentar vfs_cache_pressure além de 100 faz com que o kernel prefira recuperar dentries e inodes.

vfs_cache_pressure em 2000 faz com que a maior parte da computação ocorra nas gravações em disco RAM e disco muito atrasado).

2
user55518

Não relacionado ao cache de gravação, mas relacionado a gravações:

  • Para um sistema ext4, você pode desativar o diário completamente

    Isso reduzirá o número de gravações de disco para qualquer atualização específica, mas pode deixar o sistema de arquivos em um estado inconsistente após um desligamento inesperado, exigindo um fsck ou pior.

Para impedir que as leituras do disco disparem gravações em disco:

  • Monte com a opção relatime ou noatime

    Quando você lê um arquivo, os metadados "hora do último acesso" para esse arquivo geralmente são atualizados. A opção noatime desativará esse comportamento. Isso reduz gravações desnecessárias em disco, mas você não terá mais esses metadados. Algumas distribuições (por exemplo, Manjaro) adotaram isso como padrão em todas as partições (provavelmente para aumentar a vida útil dos SSDs de modelos anteriores).

    relatime atualiza o tempo de acesso com menos frequência, de acordo com heurísticas que ajudam a dar suporte a aplicativos que usam o atime. Este é o padrão no Red Hat Enterprise Linux.

Outras opções:

  • Nos comentários acima, Mikko compartilhou a possibilidade de montar com a opção nobarrier . Mas Ivailo citado RedHat quem adverte contra isso. Você quer 3% a mais?
1
joeytwiddle