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 todo o sistema caiba na RAM. Nesse caso, você deve usar a unidade de RAM ( tmpfs
é bom porque permite voltar ao disco, se você precisar da RAM em algum caso) para armazenamento em tempo de execução (e talvez um script initrd 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
um SSD montado em /
).
Primeiro, otimize a parte carregar-coisas-de-armazenamento-para-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
É importante notar que o gabinete do disco rígido é alto fifo_expire_async
(geralmente gravado) e longo slice_sync
para permitir que um único processo obtenha alto rendimento (definido slice_sync
como número menor se você encontrar situações em que vários processos aguardam alguns dados do disco em paralelo). A slice_idle
é sempre um compromisso para HDDs mas defini-lo em algum lugar na faixa de 3-20 deve ser aprovado de acordo com o uso do disco e firmware disco. Prefiro segmentar valores baixos, mas defini-lo muito baixo destruirá sua taxa de transferência. A quantum
configuração parece afetar muito a taxa de transferência, mas tente manter isso 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 números ambos slice_async_rq
e slice_async
muito baixos. No entanto, definir slice_async_rq
um valor muito baixo pode interromper as leituras, porque as gravações não podem mais ser adiadas após a leitura. Minha configuração vai tentar gravar dados em disco, no máximo, após 10 segundos após os dados terem sido passados ao kernel, mas desde que você pode tolerar a perda de dados sobre a perda de poder também definidos fifo_expire_async
para 3600000
dizer que uma hora é bom para o atraso no disco. Apenas mantenha o nível slice_async
baixo, pois, caso contrário, você poderá obter alta latência de leitura.
O hdparm
comando é necessário para impedir que o AAM destrua grande parte do desempenho que o AHCI + NCQ permite. 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 é a slice_idle
que deve ser definida 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 Intel 320 series, parece que a criação slide_idle
de 0
dá o melhor rendimento, mas defini-lo como 1
dá melhor (menor) latência total.
Para mais informações sobre esses ajustáveis, consulte http://www.linux-mag.com/id/7572/ .
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 fiz, não me incomodaria em definir a leitura antecipada 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 RAM suficiente para manter todo o 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 na RAM, poderá configurá-lo como 1. Se você definir como zero, o kernel não será trocado, a menos que seja absolutamente necessário para evitar o OOM. Se você estava com pouca memória e trabalhando com arquivos grandes (por exemplo, edição de vídeo em HD), pode fazer sentido definir isso próximo a 100.
Hoje em dia (2017) prefiro não ter nenhuma troca se você tiver RAM suficiente. Não ter troca normalmente perderá de 200 a 1000 MB de RAM em uma máquina desktop de longa duração. Estou disposto a sacrificar muito para evitar a latência do pior cenário possível (trocar o código do aplicativo quando a RAM estiver cheia). Na prática, isso significa que prefiro o OOM Killer à troca. Se você permitir / precisar de trocas, também poderá aumentar /proc/sys/vm/watermark_scale_factor
, 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 a documentação do kernel ) resultar em maior uso da CPU para kswapd
processos 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 alguma RAM precise ser liberada (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
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 só é sensato se você tiver apenas alguns arquivos grandes que estão sendo relidos constantemente (novamente, a edição de vídeo em HD sem RAM suficiente seria um exemplo). A documentação oficial do kernel diz que "
Exceção: se você possui uma quantidade realmente grande de arquivos e diretórios e raramente toca / lê / lista todos os arquivos com configuração vfs_cache_pressure
superior a 100 podem ser sábios. Isso se aplica apenas se você não tiver RAM suficiente e não puder manter toda a estrutura de diretórios na RAM e ainda tiver RAM suficiente para processos e cache de arquivos normais (por exemplo, servidor de arquivos para toda a empresa com muito conteúdo de arquivo). Se você sente que precisa aumentar vfs_cache_pressure
acima de 100, está executando sem RAM suficiente. Aumentar vfs_cache_pressure
pode ajudar, mas a única solução real é obter mais RAM. A vfs_cache_pressure
definição de um número alto sacrifica o desempenho médio por ter um desempenho geral mais estável (ou seja, você pode evitar um comportamento realmente ruim no pior dos casos, mas precisa lidar com um desempenho geral pior).
Por fim, diga ao kernel para usar até 99% da RAM como cache para gravações e instrua o kernel a usar até 50% da RAM antes de desacelerar o processo que está gravando (o padrão dirty_background_ratio
é 10
). Aviso: eu pessoalmente não faria isso, mas você afirmou ter RAM suficiente 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 mesmo para começar a 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
Se você colocar tudo isso /etc/rc.local
e incluir 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
, apenas faça isso se você /home
e /usr
realmente couber na RAM):
(nice find /home /usr -type f -print0 | nice ionice -c 3 wc -l --files0-from - > /dev/null)&