Após muitos testes comparativos com o sysbench, chego a esta conclusão:
Para sobreviver (em termos de desempenho) a uma situação em que
- um processo de cópia maligna inunda páginas sujas
- e cache de gravação de hardware está presente (possivelmente também sem isso)
- e leituras ou gravações síncronas por segundo (IOPS) são críticas
basta despejar todos os elevadores, filas e caches de páginas sujos. O local correto para páginas sujas está na RAM desse cache de gravação de hardware.
Ajuste dirty_ratio (ou novos dirty_bytes) o mais baixo possível, mas fique de olho na taxa de transferência seqüencial. No meu caso particular, 15 MB foram ótimos ( echo 15000000 > dirty_bytes
).
Isso é mais um hack do que uma solução, porque agora gigabytes de RAM são usados apenas para cache de leitura, em vez de cache sujo. Para que o cache sujo funcione bem nessa situação, o descarregador em segundo plano do kernel do Linux precisará calcular a velocidade com que o dispositivo subjacente aceita solicitações e ajustar a descarga em segundo plano de acordo. Díficil.
Especificações e referências para comparação:
Testado ao dd
inserir zeros no disco, o sysbench mostrou enorme sucesso , aumentando 10 threads de gravações fsync em 16 kB de 33 a 700 IOPS (limite de inatividade: 1500 IOPS) e um thread único de 8 a 400 IOPS.
Sem carga, os IOPS não foram afetados (~ 1500) e a taxa de transferência foi ligeiramente reduzida (de 251 MB / s para 216 MB / s).
dd
ligar:
dd if=/dev/zero of=dumpfile bs=1024 count=20485672
para sysbench, o test_file.0 foi preparado para não ser comparado com:
dd if=/dev/zero of=test_file.0 bs=1024 count=10485672
chamada 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 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
Blocos menores mostraram números ainda mais drásticos.
--file-block-size = 4096 com 1 GB 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 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 dirty_bytes no sistema ocioso:
sysbench 0.4.12: benchmark de avaliação de 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 (cache de gravação de 512 MB com proteção)
- Intel Xeon L5520
- 6 GiB de RAM a 1066 MHz
- Placa-mãe Supermicro X8DTN (chipset 5520)
- 12 discos Seagate Barracuda 1 TB
- 10 no software Linux RAID 10
- Kernel 2.6.32
- Sistema de arquivos xfs
- Debian instável
Em resumo, agora tenho certeza de que essa configuração terá um bom desempenho em situações ociosas, com carga alta e até com carga total para o tráfego do banco de dados que, de outra forma, teria passado fome pelo tráfego seqüencial. A taxa de transferência seqüencial é superior a dois links de gigabit, de qualquer maneira, portanto, não há problema em reduzi-la um pouco.