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). Реализация ввода / вывода в СУБД может сильно отличаться от того, что вы моделировали, от используемых системных вызовов, от нескольких файлов и заданий, выполняющих ввод / вывод, до любого количества вещей. Это стоит своего вопроса, если вы хотите продолжить расследование.

Другие вопросы по тегам