Temos processos fazendo gravações em segundo plano de arquivos grandes. Gostaríamos que esses tivessem um impacto mínimo em outros processos.
Aqui está um teste realizado no SLES11 SP4. O servidor possui memória massiva, o que permite criar 4GB de páginas sujas.
> dd if=/dev/zero of=todel bs=1048576 count=4096
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB) copied, 3.72657 s, 1.2 GB/s
> dd if=/dev/zero of=zer oflag=sync bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 16.6997 s, 0.0 kB/s
real 0m16.701s
user 0m0.000s
sys 0m0.000s
> grep Dirty /proc/meminfo
Dirty: 4199704 kB
Esta é a minha investigação até agora:
- SLES11 SP4 (3.0.101-63)
- digite ext3 (rw, nosuid, nodev, noatime)
- programador de prazos
- mais de 120 GB de memória recuperável no momento
- O dirty_ratio está definido para 40% e o dirty_background_ratio 10%, o 30s expira, o 5s writeback
Aqui estão minhas perguntas:
- com 4GB de memória suja no final do teste, concluo que o agendador de IO não foi chamado no teste acima. Está certo?
- uma vez que a lentidão persiste após terminar o primeiro dd, concluo que este problema também não tem nada a ver com o kernel alocar memória ou qualquer "copy on write" acontecendo quando dd preenche seu buffer (dd é sempre escrevendo do mesmo buf).
- existe uma maneira de investigar mais profundamente o que está bloqueado? Quaisquer contadores interessantes para assistir? Alguma idéia sobre a fonte da disputa?
- estamos pensando em reduzir os valores de dirty_ratio, executando o primeiro dd no modo síncrono. Alguma outra diretriz para investigar? Existe uma desvantagem em colocar o primeiro dd síncrono? Receio que seja priorizado em relação a outros processos de "legits" que fazem gravações assíncronas.
veja também
link
limita o fluxo de fundo do linux (páginas sujas)
link
link
EDITAR:
existe um sistema de arquivos ext2 no mesmo dispositivo. Neste dispositivo, não há nenhum congelamento! O único impacto no desempenho que ocorre durante a limpeza de páginas sujas, onde uma chamada síncrona pode levar até 0,3s, muito longe do que experimentamos com nosso sistema de arquivos ext3.
EDIT2:
Após @Matthew Ife comentar, tentei fazer a gravação síncrona abrindo o arquivo sem O_TRUNC e você não vai acreditar no resultado!
> dd if=/dev/zero of=zer oflag=sync bs=512 count=1
> dd if=/dev/zero of=todel bs=1048576 count=4096
> dd if=/dev/zero of=zer oflag=sync bs=512 count=1 conv=notrunc
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000185427 s, 2.8 MB/s
dd estava abrindo o arquivo com parâmetros:
open("zer", O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, 0666) = 3
mudando com a opção notrunc, agora é
open("zer", O_WRONLY|O_CREAT|O_SYNC, 0666) = 3
e a gravação síncrona é concluída instantaneamente!
Bem, isso não é totalmente satisfatório para o meu caso de uso (estou fazendo um msync em este moda . No entanto, agora sou capaz de rastrear o que escrever e msync estão fazendo de forma diferente!
final EDIT: Eu não posso acreditar que eu acertei isso:
link
De fato, sob o SLES11 dd está abrindo o arquivo com
open("zer", O_WRONLY|O_CREAT|O_DSYNC, 0666) = 3
e O_DSYNC == O_SYNC!
Conclusão:
Para o meu uso, eu provavelmente deveria usar
dd if=/dev/zero of=zer oflag=dsync bs=512 count=1 conv=notrunc
No SLES11, a execução oflag = sync estará realmente em execução oflag = dsync, não importa o que strace esteja dizendo.