Тюнинг Direct I/O в OpenVZ контейнерах

По умолчанию запись во все файлы, открытые без флага O_DIRECT, осуществляется через write-back cache. Это не только уменьшает latency (время ожидания) записи данных на диск для приложения (системный вызов write() завершится, как только данные будут скопированы в write-back cache, не дожидаясь реальной записи на диск), но и позволяет планировщику I/O ядра эффективнее распределять ресурсы диска между процессами, группируя I/O запросы от приложений.

При этом некоторые категории приложений, например, базы данных, сами эффективно управляют записью своих данных, выполняя большие последовательные I/O запросы. Поэтому зачастую такие приложения открывают файлы с флагом O_DIRECT, который указывает ядру писать данные в такой файл, минуя write-back cache, напрямую из памяти пользовательского приложения. В случае работы одной базы данных на хосте такой подход оказывается эффективнее, чем запись через кэш, поскольку I/O запросы от базы данных уже выстроены оптимальным образом и нет необходимости в дополнительном копировании памяти из пользовательского приложения в write-back cache.

В случае работы нескольких контейнеров с базами данных на одном хосте данное предположение оказывается неверным, так как планировщик I/O в ядре Linux не может оптимально распределять ресурсы диска между приложениями, использующими Direct I/O. Поэтому по умолчанию в ядре OpenVZ Direct I/O для контейнеров выключено, и все данные пишутся через write-back cache. Это вносит небольшие накладные расходы в виде дополнительного копирования памяти из пользовательского приложения в write-back cache, при этом позволяя планировщику I/O ядра эффективнее распределять ресурсы диска.

Если заранее известно, что подобной ситуации на хосте не будет, то можно избежать дополнительных накладных расходов и разрешить использование Direct I/O всем или части контейнеров. Настроить поведение ядра можно, используя файл /proc/sys/fs/odirect_enable. Возможные значения данного файла в случае настройки на host node (глобальные настройки):

0 флаг O_DIRECT игнорируется для контейнеров, вся запись происходит через write-back cache (значение по умолчанию)
1 флаг O_DIRECT в контейнерах работает как обычно

Возможные значения данного файла в случае настройки внутри конкретного контейнера:

0 флаг O_DIRECT игнорируется для данного контейнера, вся запись происходит через write-back cache
1 флаг O_DIRECT для данного контейнера работает как обычно
2 использовать глобальные настройки (значение по умолчанию)

Со значением по-умолчанию:

~]# fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=sb_random_read_write.fio --bs=4k --iodepth=64 --runtime=60 --size=5G --readwrite=randrw --rwmixread=75
test: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
fio-3.7
Starting 1 process
test: Laying out IO file (1 file / 5120MiB)
Jobs: 1 (f=1): [m(1)][100.0%][r=38.5MiB/s,w=13.0MiB/s][r=9861,w=3330 IOPS][eta 00m:00s]
test: (groupid=0, jobs=1): err= 0: pid=11788: Fri Sep 27 11:08:10 2019
   read: IOPS=9843, BW=38.5MiB/s (40.3MB/s)(2307MiB/60004msec)
   bw (  KiB/s): min=13240, max=44328, per=99.98%, avg=39366.13, stdev=2658.96, samples=120
   iops        : min= 3310, max=11082, avg=9841.51, stdev=664.75, samples=120
  write: IOPS=3296, BW=12.9MiB/s (13.5MB/s)(773MiB/60004msec)
   bw (  KiB/s): min= 3928, max=14648, per=99.98%, avg=13184.47, stdev=995.44, samples=120
   iops        : min=  982, max= 3662, avg=3296.10, stdev=248.85, samples=120
  cpu          : usr=4.89%, sys=20.72%, ctx=590678, majf=0, minf=23
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.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.0%, 64=0.1%, >=64=0.0%
     issued rwts: total=590649,197829,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
   READ: bw=38.5MiB/s (40.3MB/s), 38.5MiB/s-38.5MiB/s (40.3MB/s-40.3MB/s), io=2307MiB (2419MB), run=60004-60004msec
  WRITE: bw=12.9MiB/s (13.5MB/s), 12.9MiB/s-12.9MiB/s (13.5MB/s-13.5MB/s), io=773MiB (810MB), run=60004-60004msec

Ниже указаны результаты тестирования I/O с помощью fio.
С включенным O_DIRECT:

~]# fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=sb_random_read_write.fio --bs=4k --iodepth=64 --runtime=60 --size=5G --readwrite=randrw --rwmixread=75
test: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
fio-3.7
Starting 1 process
Jobs: 1 (f=1): [m(1)][87.5%][r=555MiB/s,w=184MiB/s][r=142k,w=47.0k IOPS][eta 00m:01s]
test: (groupid=0, jobs=1): err= 0: pid=12776: Fri Sep 27 11:09:09 2019
   read: IOPS=126k, BW=493MiB/s (517MB/s)(3837MiB/7784msec)
   bw (  KiB/s): min=132752, max=589048, per=100.00%, avg=538458.86, stdev=117406.45, samples=14
   iops        : min=33188, max=147262, avg=134614.57, stdev=29351.57, samples=14
  write: IOPS=42.2k, BW=165MiB/s (173MB/s)(1283MiB/7784msec)
   bw (  KiB/s): min=44120, max=196824, per=100.00%, avg=179933.71, stdev=39267.65, samples=14
   iops        : min=11030, max=49206, avg=44983.43, stdev=9816.91, samples=14
  cpu          : usr=24.66%, sys=74.74%, ctx=5104, majf=0, minf=24
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.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.0%, 64=0.1%, >=64=0.0%
     issued rwts: total=982350,328370,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
   READ: bw=493MiB/s (517MB/s), 493MiB/s-493MiB/s (517MB/s-517MB/s), io=3837MiB (4024MB), run=7784-7784msec
  WRITE: bw=165MiB/s (173MB/s), 165MiB/s-165MiB/s (173MB/s-173MB/s), io=1283MiB (1345MB), run=7784-7784msec

В случае если на HW ноде расположен только один контейнер с нагруженной БД с включенным innodb_flush_method=O_DIRECT, то стоит включать O_DIRECT:

# cat /proc/sys/fs/odirect_enable
1

Related posts:

  1. Как измерить производительность диска в Linux? В данной статье я расскажу как измерять IOPS на вашем...
  2. OpenVZ: полезные команды для работы с контейнерами Решил собрать все в одном месте, потому что часто что-то...
  3. Установка Netams-3.4.5 под Centos. Настройка и тюнинг Бесплатное программное обеспечение NETAMS 4.0 (релиз 489 от 4 марта)...
  4. OpenVZ: полезные команды на заметку Добавить сетевой интерфейс сервера контейнеру, на примере eth1 (уточнение: это...
  5. OpenVZ: как настроить bridge с контейнером Установка ПО на физическом сервере: Создаем vmbr0 интерфейс: Удаляем IP...
Both comments and pings are currently closed.

Comments are closed.