SSD IOPS в Linux, DIRECT намного быстрее, чем в буфере, fio
У меня есть аппаратная система RAID-6 размером 30 ТБ (LSI 9280-8e) из 10 твердотельных накопителей Intel DC-S4500, которая используется для целей базы данных. ОС Debian 7.11 с ядром 3.2. Файловая система смонтирована в XFS с опцией nobarrier.
Видя несколько вялое сравнение с моими ожиданиями производительности при случайном вводе / выводе, я начал исследовать, что происходит, запустив тесты fio. И к моему удивлению, когда я только что использовал файл fio для файла 1Tb в режиме случайного чтения с (iodepth=32 и ioengine=libaio), я получаю ~ 3000 IOPS, что намного ниже, чем я ожидал.
random-read: (groupid=0, jobs=1): err= 0: pid=128531
read : io=233364KB, bw=19149KB/s, iops=4787 , runt= 12187msec
...
cpu : usr=1.94%, sys=5.81%, ctx=58484, majf=0, minf=53
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=99.9%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
issued : total=r=58341/w=0/d=0, short=r=0/w=0/d=0
Однако, если я использую опцию direct =1 (т.е. обходя буферный кеш linux), я получаю ~ 40000 IOPS, что я и хотел бы увидеть.
random-read: (groupid=0, jobs=1): err= 0: pid=130252
read : io=2063.7MB, bw=182028KB/s, iops=45507 , runt= 11609msec
....
cpu : usr=6.93%, sys=23.29%, ctx=56503, majf=0, minf=54
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=100.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
issued : total=r=528291/w=0/d=0, short=r=0/w=0/d=0
Кажется, у меня есть все правильные настройки для раздела SSD в форме планировщика, упреждающего чтения и настройки вращения.
root@XX:~# cat /sys/block/sdd/queue/scheduler
[noop] deadline cfq
root@XX:~# cat /sys/block/sdd/queue/rotational
0
root@XX:~# blockdev --getra /dev/sdd
0
Я все еще пропускаю что-то, что так сильно снижает производительность буферизации? Или ожидается, что вы увидите такую разницу между DIRECT и буферизованным?
Я также посмотрел на вывод iostat во время двух запусков. Это когда прямой =1 был использован:
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sdd 0.00 0.00 48110.00 0.00 192544.00 0.00 8.00 27.83 0.58 0.58 0.00 0.02 99.60
Это забуференный прогон
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sdd 0.00 0.00 4863.00 0.00 19780.00 0.00 8.13 0.89 0.18 0.18 0.00 0.18 85.60
Таким образом, похоже, что ключевым отличием является размер очереди (avgqu-sz), который является небольшим при использовании буферизованного ввода-вывода. Я нахожу это странным, учитывая, что nr_requests и queue_depth все высокие:
root@XX:~# cat /sys/block/sdd/queue/nr_requests
128
root@XX:~# cat /sys/block/sda/device/queue_depth
256
Любой совет здесь?
1 ответ
Debian 7.11 с ядром 3.2
Обновите, если это вообще возможно. Мало того, что вы получаете улучшения ядра, но Wheezy это конец жизни.
Да, вы видите более высокую загрузку и глубину очереди, когда direct=1. В руководстве fio, в частности, упоминается этот случай (выделение мое):
iodepth = INT
Количество модулей ввода / вывода, которые нужно оставить в полете против файла. Обратите внимание, что увеличение iodepth за 1 не повлияет на синхронные ioengines (за исключением небольших степеней, когда используется verify_async). Даже асинхронные движки могут накладывать ограничения ОС, приводя к тому, что желаемая глубина не достигается. Это может произойти в Linux, когда используется libaio и не задано прямое =1, поскольку буферизованный ввод / вывод не асинхронен в этой ОС. Следите за распределением глубины ввода / вывода на выходе fio, чтобы убедиться, что достигнутая глубина соответствует ожидаемой
Так что libaio требует O_DIRECT для асинхронного, важная деталь реализации, которую нужно знать. Кто-то спросил, не является ли прямая связь с libaio хорошей идеей:
Допустимо ли устанавливать direct=0 при использовании libaio?
Вы можете сделать это, но я бы не рекомендовал это. В современных ядрах Linux отправка libaio, скорее всего, станет блокирующей (и, следовательно, больше не асинхронной) без O_DIRECT, что может ограничить количество достигнутых параллельных операций ввода-вывода. Есть веский аргумент, что примеры fio НЕ должны поощрять такую комбинацию вариантов...
что означает "стоящее в очереди" поведение в документе man?
Если вы имеете в виду предложение "Обратите внимание, что Linux может поддерживать поведение в очереди только с небуферизованным вводом-выводом" (см. http://fio.readthedocs.io/en/latest/fio_doc.html), я думаю, что это пытаясь сказать:
"Вместо того, чтобы блокировать системный вызов отправки до тех пор, пока не прекратится ввод-вывод и не вернутся с самого нижнего дискового устройства (поведение блокировки), при использовании direct = 1 с libaio вы можете отправить ввод-вывод и асинхронно поставить его в очередь. Ядро, позволяющее системному вызову отправки возвращаться сразу и открывающее для вас возможность ставить в очередь другие представления до завершения ввода-вывода ".
Также попробуйте контрольный тест с ioengine=psync и direct=0. Даже синхронные записи с кешем могут сделать много операций ввода-вывода в секунду.
Все это обходит реальный вопрос: в чем заключалась проблема с рабочей нагрузкой базы данных? Симптомы проблемы, версии программного обеспечения, конфигурация, показатели производительности (iostat). Реализация ввода / вывода в СУБД может сильно отличаться от того, что вы моделировали, от используемых системных вызовов, от нескольких файлов и заданий, выполняющих ввод / вывод, до любого количества вещей. Это стоит своего вопроса, если вы хотите продолжить расследование.