confuso sobre a velocidade de gravação do dd e o cache da página VFS

confuso sobre a velocidade de gravação do dd e o cache da página VFS

Depois de ler alguns artigos sobre o cache de páginas VFS do Linux e os parâmetros ajustáveis, dirty_ratiotive a impressão de que o cache de páginas funcionaria como camada de cache de leitura e gravação.

Mas usar o teste simples abaixo funciona bem para melhorar a velocidade de leitura de arquivos localizados no cache da página, mas que não parecem funcionar nas gravações.

por exemplo

Limpe o cache e grave no arquivo.

# swapoff -a
# echo 3 > /proc/sys/vm/drop_caches

# dd if=/dev/zero of=/home/flo/test bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.182474 s, 172 MB/s

Verifique se o arquivo está realmente no cache da página

# vmtouch /home/flo/test 
           Files: 1
     Directories: 0
  Resident Pages: 7680/7680  30M/30M  100%
         Elapsed: 0.000673 seconds

Leia o arquivo para confirmar se realmente vem do cache.

# dd if=/home/flo/test of=/dev/null bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.00824169 s, 3.8 GB/s

Elimine o cache e leia novamente para provar a diferença de velocidade.

# echo 3 > /proc/sys/vm/drop_caches
# dd if=/home/flo/test of=/dev/null bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.132531 s, 237 MB/s

Como não estou usando DIRECT_IO com dd, esperava que o cache da página fosse usado como um tipo de cache de write-back. E com base em dirty_ratioou dirty_expire_centiseconds... eventualmente os dados seriam confirmados no disco.

Alguém pode explicar como o VFS lida com o processo de leitura e gravação de maneira diferente, especialmente durante as gravações, e por que não há ganho de velocidade.

Existe alguma maneira de tornar o vfs mais agressivo no cache de gravação para que ele se comporte mais como o cache de write-back que você pode encontrar em um controlador RAID, por exemplo.

Obrigado

fLo

Responder1

man ext4 tem esta introdução sobre auto_da_alloca opção (no):

Muitos aplicativos quebrados não usam fsync()...

Parece haver uma longa história (alguma tragédia sobre perda de dados) por trás disso. Tem a ver comalocação atrasadade blocos do sistema de arquivos. Ext2/3 não tinha isso, mas é um recurso muito importante não apenas do ext4.

Se o aplicativo não sincronizar, nem o usuário manualmente, e o kernel somente após 30 segundos, é melhor que o sistema de arquivos faça isso imediatamente quando alguma reescrita de arquivo estiver envolvida. Caso contrário, com o DA, coisas ruins podem acontecer facilmente em caso de falha de energia. Coisas piores do que apenas perder as últimas alterações.

Sem conv=notruncateo comando dd atua como um "aplicativo" ao substituir. É necessário se livrar do arquivo existente para criar o novo, caso contrário você obterá uma mistura se o arquivo existente for mais longo.

Com mount -o remount,noauto_da_alloc ...você pode desativar esse comportamento no ext4. Agora a escrita do bloco pode ser feita muito tempo após o truncamento.

Nas próximasnível de agressãoseria aumentar o tempo de expiração de 30s e o intervalo de verificação de 5s (os valores dirty_..._centisecs em /proc/sys/vm/) para os writebacks periódicos. Com o padrão 30/5, alguns novos arquivos serão gravados meio minuto depois, a menos que você seja muito rápido para excluí-los mais rapidamente.

Quanto mais agressivo o VFS for com as páginas não utilizadas, menos agressivo o sistema de arquivos deverá ser com o dispositivo de bloco.


Opções de montagem e parâmetros de writeback

]# findmnt --real
TARGET       SOURCE     FSTYPE OPTIONS
/            /dev/sda3  ext4   rw,relatime,noauto_da_alloc
|-/root/sda1 /dev/sda1  ext2   rw,relatime
`-/root/16   /dev/sda16 ext4   rw,relatime

Em uma configuração como essa, uma substituição é sincronizada imediatamente no sda16, mas não nos outros dois.

No momento eu (acho que) desliguei completamente o write-back periódico.

]# grep '' /proc/sys/vm/*centisecs
/proc/sys/vm/dirty_expire_centisecs:720000
/proc/sys/vm/dirty_writeback_centisecs:0

E agora finalmente estou reunindo páginas sujas:

]# grep nr_dirty /proc/vmstat 
nr_dirty 10077
nr_dirty_threshold 437320
nr_dirty_background_threshold 174671

EUtentarpara reuni-los e chegar de alguma forma perto da proporção de fundo padrão de 10% - fui sincronizado ontem quando fui suspender para o RAM. Faz sentido: quem quer dormir com MBs de páginas sujas?

mm/writeback.cé muito complexo em detalhes, dizem os comentários. Um problema é não perder o ponto de estrangulamento quando "1000 dd começam a sujar de uma vez". O "Writeback" parece ter como objetivo uma proporção de 10% de glicemia, no longo prazo. Como meu exemplo acima mostra, esses 10% (da RAM total/disponível) demoram muito para serem preenchidos sob uso normal (mínimo). Um minuto de navegação suja 1.000 páginas, aproximadamente.


Depois da teoria, a prova específica

Testei 10 blocos em dois dos sistemas de arquivos listados acima:

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0076396 s, 1.4 GB/s

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00514406 s, 2.0 GB/s

-> com noauto_da_alloc na partição raiz (sda3, acima) a substituição é ainda mais rápida.

No ext4 montado padrão (sda16 acima), ele fica mais lento:

]# rm test10 

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00800839 s, 1.3 GB/s

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0740824 s, 142 MB/s

... porque toda a substituição é sincronizada, como vmstat 1 |cut...mostra:

    0     0
    0     0
    0     0
-----io----
   bi    bo
    0 10240
    0     0
    0     0

Manualmente synccom alocação atrasada

O bom disso é que você faz isso quando quiser e pode fazer isso em arquivos únicos, mas também em unidades inteiras.

Além disso: desmontar, desligar (e suspender) está incluído.

O ruim é: risco de "corrupção" de comprimento zero quando ocorre uma falha/falha de energia entre uma gravação (sobre) e uma sincronização. O que significa que você realmente só tem como segurança o que coloca em um ou dois armazenamentos externos.


Não consigo encontrar um resultado final. Não existe uma solução fácil, apenas explicações longas (mas pelo menos lógicas).

Responder2

Para ver o comportamento rápido, tenho que fazer rm testprimeiro. Por exemplo, vejo ddo relatório de 1 GB/s em vez de 150 MB/s.

Referências:

Embora as referências apenas expliquem por que pensei em tentar isso, na verdade não explicam por que causa o bloqueio do IO.

No meu computador, o bloqueio parecia acontecer apenas dentro do novo código WBT ("writeback throttling")... que foi adicionado em 2016,depoisvocê fez sua pergunta. eu não analiseipor queisso causaria isso. E desapareceu quando o WBT foi desativado.

Minha versão do kernel é 4.18.16-200.fc28.x86_64.

strace -Tmostra que todo o tempo foi gasto em close(), o que faz mais sentido para mim. Tentei usar perftambém. Não funcionou como deveria, mas mostrou rastreamentos de pilha como

dd 17068 [003] 475165.381526:       sched:sched_switch: dd:17068 [120] T ==> kworker/3:1H:19326 [100]
    ffffffffa390c172 __sched_text_start+0x352 ([kernel.kallsyms])
    ffffffffa390c172 __sched_text_start+0x352 ([kernel.kallsyms])
    ffffffffa390c6a8 schedule+0x28 ([kernel.kallsyms])
    ffffffffa30def32 io_schedule+0x12 ([kernel.kallsyms])
    ffffffffa3461ed7 wbt_wait+0x337 ([kernel.kallsyms])
    ffffffffa342ee33 blk_queue_bio+0x123 ([kernel.kallsyms])
    ffffffffa342d114 generic_make_request+0x1a4 ([kernel.kallsyms])
    ffffffffa342d3c5 submit_bio+0x45 ([kernel.kallsyms])
    ffffffffa3377d78 ext4_io_submit+0x48 ([kernel.kallsyms])
    ffffffffa335da2c ext4_writepages+0x70c ([kernel.kallsyms])
    ffffffffa3209311 do_writepages+0x41 ([kernel.kallsyms])
    ffffffffa31f808e __filemap_fdatawrite_range+0xbe ([kernel.kallsyms])
    ffffffffa334b9ec ext4_release_file+0x6c ([kernel.kallsyms])
    ffffffffa32a9d4e __fput+0xae ([kernel.kallsyms])
    ffffffffa30cf474 task_work_run+0x84 ([kernel.kallsyms])
    ffffffffa3003e6e exit_to_usermode_loop+0xce ([kernel.kallsyms])
    ffffffffa300425d do_syscall_64+0x14d ([kernel.kallsyms])
    ffffffffa3a00088 entry_SYSCALL_64_after_hwframe+0x44 ([kernel.kallsyms])
        7fcca3a60654 __close+0x14 (/usr/lib64/libc-2.27.so)

o que me lembrou que eu estava testando o deadlineagendador de E/S, com WBT ("writeback throttling") habilitado. Desativar o WBT (inclusive mudando para CFQ, que é incompatível) me deu um comportamento rápido novamente!

Os perfcomandos que usei para ver isso foram:

sudo perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -gP -o ~/perf.data dd if=/dev/zero of=test bs=1M count=30
sudo perf script -i ~/perf.data | cat

Responder3

Só não use dd. Por exemplo, use cpe você obterá o pagecache para gravações, tudo bem.

informação relacionada