Limitar o flush de fundo do Linux (páginas sujas)

25

A limpeza em segundo plano no Linux ocorre quando um excesso de dados gravados está pendente (ajustável por / proc / sys / vm / dirty_background_ratio) ou um tempo limite para gravações pendentes é atingido (/ proc / sys / vm / dirty_expire_centisecs). A menos que outro limite esteja sendo atingido (/ proc / sys / vm / dirty_ratio), mais dados gravados podem ser armazenados em cache. Outras gravações serão bloqueadas.

Em teoria, isso deve criar um processo em segundo plano, escrevendo páginas sujas sem perturbar outros processos. Na prática, ele perturba qualquer processo fazendo leitura não sincronizada ou escrita síncrona. Seriamente. Isso ocorre porque o flush de fundo realmente grava em 100% da velocidade do dispositivo e qualquer outra solicitação de dispositivo neste momento será atrasada (porque todas as filas e os caches de gravação na estrada estão cheios).

Existe uma maneira de limitar a quantidade de solicitações por segundo que o processo de limpeza realiza, ou efetivamente priorizar outras E / S de dispositivos?

    
por korkman 25.03.2010 / 21:48

3 respostas

19

Após vários testes de benchmarking com o sysbench, chego a esta conclusão:

Para sobreviver (performance-wise) uma situação em que

  • um processo de cópia malvado inunda páginas sujas
  • e o cache de gravação de hardware está presente (possivelmente também sem isso)
  • e leituras síncronas ou gravações por segundo (IOPS) são críticas

apenas descarregue todos os elevadores, filas e caches de páginas sujas. O local correto para páginas sujas está na RAM desse cache de gravação de hardware.

Ajuste o dirty_ratio (ou new dirty_bytes) o mais baixo possível, mas fique de olho no throughput sequencial. No meu caso particular, 15 MB foram ótimos ( echo 15000000 > dirty_bytes ).

Isso é mais um truque do que uma solução, porque gigabytes de RAM agora são usados para cache de leitura apenas em vez de cache sujo. Para que o cache sujo funcione bem nessa situação, o flusher de plano de fundo do kernel do Linux precisaria calcular a média em que velocidade o dispositivo subjacente aceita solicitações e ajustar o fluxo de fundo de acordo. Não é fácil.

Especificações e benchmarks para comparação:

Testado enquanto dd 'zeros em disco, sysbench mostrou enorme sucesso , aumentando 10 threads em fsync escreve em 16 kB de 33 a 700 IOPS (limite ocioso: 1500 IOPS) e thread único de 8 a 400 IOPS.

Sem carga, as IOPS não foram afetadas (~ 1500) e o rendimento foi ligeiramente reduzido (de 251 MB / s para 216 MB / s).

dd call:

dd if=/dev/zero of=dumpfile bs=1024 count=20485672

para o sysbench, o test_file.0 foi preparado para não ser utilizado com:

dd if=/dev/zero of=test_file.0 bs=1024 count=10485672

chamada do sysbench para 10 threads:

sysbench --test=fileio --file-num=1 --num-threads=10 --file-total-size=10G --file-fsync-all=on --file-test-mode=rndwr --max-time=30 --file-block-size=16384 --max-requests=0 run

Chamada do sysbench para um thread:

sysbench --test=fileio --file-num=1 --num-threads=1 --file-total-size=10G --file-fsync-all=on --file-test-mode=rndwr --max-time=30 --file-block-size=16384 --max-requests=0 run

Tamanhos menores de blocos mostraram números ainda mais drásticos.

- file-block-size = 4096 com 1 GB de dirty_bytes:

sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 30 Write, 30 Other = 60 Total
Read 0b  Written 120Kb  Total transferred 120Kb  (3.939Kb/sec)
      0.98 Requests/sec executed

Test execution summary:
      total time:                          30.4642s
      total number of events:              30
      total time taken by event execution: 30.4639
      per-request statistics:
           min:                                 94.36ms
           avg:                               1015.46ms
           max:                               1591.95ms
           approx.  95 percentile:            1591.30ms

Threads fairness:
      events (avg/stddev):           30.0000/0.00
      execution time (avg/stddev):   30.4639/0.00

- file-block-size = 4096 com 15 MB de dirty_bytes:

sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 13524 Write, 13524 Other = 27048 Total
Read 0b  Written 52.828Mb  Total transferred 52.828Mb  (1.7608Mb/sec)
    450.75 Requests/sec executed

Test execution summary:
      total time:                          30.0032s
      total number of events:              13524
      total time taken by event execution: 29.9921
      per-request statistics:
           min:                                  0.10ms
           avg:                                  2.22ms
           max:                                145.75ms
           approx.  95 percentile:              12.35ms

Threads fairness:
      events (avg/stddev):           13524.0000/0.00
      execution time (avg/stddev):   29.9921/0.00

- file-block-size = 4096 com 15 MB de dirty_bytes no sistema inativo:

sysbench 0.4.12: referência de avaliação do sistema multiencadeado

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 43801 Write, 43801 Other = 87602 Total
Read 0b  Written 171.1Mb  Total transferred 171.1Mb  (5.7032Mb/sec)
 1460.02 Requests/sec executed

Test execution summary:
      total time:                          30.0004s
      total number of events:              43801
      total time taken by event execution: 29.9662
      per-request statistics:
           min:                                  0.10ms
           avg:                                  0.68ms
           max:                                275.50ms
           approx.  95 percentile:               3.28ms

Threads fairness:
      events (avg/stddev):           43801.0000/0.00
      execution time (avg/stddev):   29.9662/0.00

Sistema de teste:

  • Adaptec 5405Z (esse cache de gravação de 512 MB com proteção)
  • Intel Xeon L5520
  • 6 GiB RAM @ 1066 MHz
  • Motherboard Supermicro X8DTN (chipset 5520)
  • 12 discos Seagate Barracuda 1 TB
    • 10 no RAID 10 do software Linux
  • Kernel 2.6.32
  • Sistema de arquivos xfs
  • Debian instável

Em resumo, agora estou certo de que essa configuração terá um bom desempenho em situações ociosas, de alta carga e até de carga total para tráfego de banco de dados que, de outra forma, teria sido afetado pelo tráfego sequencial. A taxa de transferência sequencial é superior a dois links gigabit que podem ser entregues de qualquer maneira, portanto, não há problema em reduzi-la um pouco.

    
por 11.04.2010 / 13:03
3

Apesar de os parâmetros de kernel de ajuste terem parado o problema, é possível que seus problemas de desempenho tenham sido o resultado de um bug no controlador Adaptec 5405Z que foi corrigido em uma atualização de firmware de 1º de fevereiro de 2012. As notas da versão dizem "Corrigido um problema em que o firmware podia travar durante alta tensão de E / S". Talvez espalhar a E / S como você foi o suficiente para evitar que esse bug seja acionado, mas isso é apenas um palpite.

Estas são as notas da versão: link

Mesmo que esse não fosse o caso da sua situação específica, imaginei que isso poderia beneficiar os usuários que se depararem com essa postagem no futuro. Vimos algumas mensagens como as que seguem em nossa saída do dmesg, que eventualmente nos levaram à atualização do firmware:

aacraid: Host adapter abort request (0,0,0,0)
[above was repeated many times]
AAC: Host adapter BLINK LED 0x62
AAC0: adapter kernel panic'd 62.
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000000
Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT,SUGGEST_OK
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000028
Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT,SUGGEST_OK
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000028

Aqui estão os números de modelo dos controladores RAID da Adaptec listados nas notas de versão do firmware que possui a alta correção de travamento de E / S: 2045, 2405, 2405Q, 2805, 5085, 5405, 5405Z, 5445, 5445Z , 5805, 5805Q, 5805Z, 5805ZQ, 51245, 51645, 52445.

    
por 15.07.2014 / 19:08
0

Qual é a sua média para o Dirty em / proc / meminfo? Normalmente, isso não deve exceder seu / proc / sys / vm / dirty_ratio. Em um servidor de arquivos dedicado, eu tenho o dirty_ratio configurado para uma porcentagem muito alta de memória (90), já que nunca excederei isso. Sua dirty_ration é muito baixa, quando você acerta, tudo acontece, aumente.

    
por 10.04.2010 / 22:37