Gerar muitas páginas sujas está bloqueando gravações síncronas

5

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.

    
por freedge 08.12.2015 / 07:02

3 respostas

3

Algumas coisas que eu gostaria de saber o resultado.

  1. inicialmente criando o arquivo grande com fallocate e escrevendo nele.

  2. Configurando dirty_background_bytes muito abaixo (digamos 1GiB) e usando CFQ como agendador. Note que neste teste pode ser uma melhor representação para executar o pequeno no meio da grande corrida.

Portanto, para a opção 1, você pode evitar todas as semânticas data=ordered , pois a alocação de blocos já foi feita (e rapidamente) porque foi pré-alocada via fallocate e os metadados foram configurados antes da gravação. Seria útil testar se esse é realmente o caso. Eu tenho alguma confiança, embora isso melhore o desempenho.

Para a opção 2, você pode usar o ionice um pouco mais. O prazo final é comprovadamente mais rápido que o CFQ, embora o CFQ tente organizar o IO por processo, de modo que você descubra que ele oferece uma melhor participação do IO através de cada processo.

Eu li em algum lugar (não consigo encontrar uma fonte agora) que o dirty_background_ratio irá bloquear as gravações contra o processo de commit individual (efetivamente tornando o grande processo mais lento) para evitar que um processo perca todos os outros. Dada a pouca informação que posso encontrar agora sobre esse comportamento, tenho menos confiança de que isso funcionará.

Ah: eu devo salientar que fallocate confia em extensões e você precisará usar o ext4.

    
por 13.12.2015 / 11:37
2

Estou respondendo às minhas próprias perguntas, mas se alguém puder sugerir algo melhor, eu ficaria muito grato:)

having 4GB dirty memory at the end of the test, I conclude that the IO scheduler has not been called in above test. Is that right?

Isso está completamente errado. A quantidade de memória suja não é um bom indicador. Isto pode ser facilmente provado apenas rodando o iostat e verifique se muita escrita está acontecendo quando o dd oflag = sync está rodando.

is there a way to investigate deeper what is blocked? Any interesting counters to watch?

perf record -e 'jbd:*' -e 'block:*' -ag

Para kernels mais novos, substitua jbd por jbd2.

Any idea on the source of the contention?

Na verdade, para um ext3 com data = ordered , o thread journing é responsável por liberar os dados no disco. O flush acontece na ordem das gravações. A frequência de descarga pode ser controlada usando a opção commit ao montar o sistema de arquivos.

Um experimento interessante: monte o sistema de arquivos com commit = 60 e desative o encadeamento de write-back. Ao executar o primeiro dd, ele é concluído em 2s, e o iostat mostra que nenhum IO foi gerado!

Ao executar o segundo dd com oflag = sync, todos os IO gerados pelo primeiro dd são liberados para o disco.

we are thinking of either reducing the dirty_ratio values, either performing the first dd in synchronous mode.

para o registro, ambas as soluções dão bons resultados. Outra boa ideia é colocar esses arquivos grandes em um sistema de arquivos separado (possivelmente montado com data = writeback)

Isso não está vinculado especificamente ao SLES11 ou a kernels mais antigos. O mesmo comportamento é experimentado em todos os kernels que eu tentei.

    
por 09.12.2015 / 13:50
1

Este é o comportamento esperado do ext3: Neste sistema de arquivos, o bloco de gravações síncronas até que todos os blocos sujos anteriores sejam gravados no disco. Esse é o motivo exato pelo qual os desenvolvedores ignoraram completamente as gravações sincronizadas nos últimos anos.

Ext4, XFS, ZFS e BTRFS são muito melhores nesse aspecto. Considerando que ext4 é um substituto mais ou menos drop-in para ext3, você deve realmente atualizar seu sistema de arquivos.

    
por 13.12.2015 / 15:42