Назад | Перейти на главную страницу

Ограничьте фоновую очистку Linux (грязные страницы)

Фоновая очистка в Linux происходит, когда либо отложено слишком много записанных данных (регулируется с помощью / proc / sys / vm / dirty_background_ratio), либо достигнут тайм-аут для отложенных записей (/ proc / sys / vm / dirty_expire_centisecs). Если не будет достигнут другой предел (/ proc / sys / vm / dirty_ratio), больше записанных данных могут быть кэшированы. Дальнейшие записи будут заблокированы.

Теоретически это должно создать фоновый процесс, записывающий грязные страницы, не мешая другим процессам. На практике это мешает любому процессу, выполняющему некэшированное чтение или синхронную запись. Плохо. Это связано с тем, что фоновая очистка фактически выполняет запись со 100% скоростью устройства, а любые другие запросы устройств в это время будут задерживаться (потому что все очереди и кеши записи на дороге заполнены).

Есть ли способ ограничить количество запросов в секунду, выполняемых процессом очистки, или иным образом эффективно установить приоритеты ввода-вывода других устройств?

После большого количества тестов с помощью sysbench я пришел к такому выводу:

Чтобы выжить (с точки зрения производительности) в ситуации, когда

  • злой процесс копирования наводняет грязные страницы
  • и аппаратный кэш записи присутствует (возможно, и без него)
  • и синхронные чтения или записи в секунду (IOPS) критичны

просто сбросьте все лифты, очереди и грязные кеши страниц. Правильное место для грязных страниц - это ОЗУ этого аппаратного кэша записи.

Настройте dirty_ratio (или новые dirty_bytes) как можно ниже, но следите за последовательной пропускной способностью. В моем конкретном случае оптимальным было 15 МБ (echo 15000000 > dirty_bytes).

Это скорее взлом, чем решение, потому что гигабайты оперативной памяти теперь используются только для кэширования чтения вместо грязного кеша. Чтобы грязный кеш работал хорошо в этой ситуации, фоновой очистке ядра Linux потребуется усреднить, с какой скоростью базовое устройство принимает запросы, и соответствующим образом настроить фоновую очистку. Нелегко.


Технические характеристики и тесты для сравнения:

Проверено пока ddвывод нулей на диск, как показал sysbench огромный успех, увеличивая 10 потоков, которые fsync пишет на 16 КБ, с 33 до 700 IOPS (предел простоя: 1500 IOPS) и одиночный поток с 8 до 400 IOPS.

Без нагрузки количество операций ввода-вывода в секунду не изменилось (~ 1500), а пропускная способность немного снизилась (с 251 МБ / с до 216 МБ / с).

dd вызов:

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

для sysbench test_file.0 был подготовлен к неразложению с помощью:

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

вызов sysbench для 10 потоков:

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

вызов sysbench для одного потока:

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

Меньшие размеры блоков показали еще более резкие цифры.

--file-block-size = 4096 с грязными_байтами 1 ГБ:

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 с грязными_байтами 15 МБ:

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 с 15 МБ dirty_bytes в неактивной системе:

sysbench 0.4.12: тест оценки многопоточной системы

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

Тест-система:

  • Adaptec 5405Z (это 512 МБ кеша записи с защитой)
  • Intel Xeon L5520
  • 6 ГиБ ОЗУ @ 1066 МГц
  • Материнская плата Supermicro X8DTN (чипсет 5520)
  • 12 дисков Seagate Barracuda 1 ТБ
    • 10 в программном массиве Linux RAID 10
  • Ядро 2.6.32
  • Файловая система xfs
  • Нестабильный Debian

Таким образом, теперь я уверен, что эта конфигурация будет хорошо работать в ситуациях простоя, высокой нагрузки и даже полной нагрузки для трафика базы данных, который в противном случае был бы ограничен последовательным трафиком. Последовательная пропускная способность в любом случае выше, чем могут обеспечить два гигабитных канала, поэтому нет проблем с ее небольшим уменьшением.

Несмотря на то, что настройка параметров ядра устранила проблему, на самом деле вполне возможно, что проблемы с производительностью были результатом ошибки в контроллере Adaptec 5405Z, которая была исправлена ​​в обновлении прошивки от 1 февраля 2012 года. В примечаниях к выпуску говорится: «Устранена проблема, из-за которой прошивка могла зависать при высокой нагрузке на ввод-вывод». Возможно, распределения ввода-вывода, как вы, было достаточно, чтобы предотвратить запуск этой ошибки, но это только предположение.

Вот примечания к выпуску: http://download.adaptec.com/pdfs/readme/relnotes_arc_fw-b18937_asm-18837.pdf

Даже если это не относится к вашей конкретной ситуации, я подумал, что это может принести пользу пользователям, которые встретят этот пост в будущем. В наших выводах dmesg мы увидели несколько сообщений, которые в конечном итоге привели нас к обновлению прошивки:

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

Вот номера моделей RAID-контроллеров Adaptec, которые перечислены в примечаниях к выпуску для микропрограммного обеспечения с исправлением зависания высокого уровня ввода-вывода: 2045, 2405, 2405Q, 2805, 5085, 5405, 5405Z, 5445, 5445Z, 5805, 5805Q, 5805Z, 5805ZQ, 51245, 51645, 52445.

Ядро, которое включает "WBT":

Улучшения в блочном слое, LWN.net

При регулировании обратной записи [блочный уровень] пытается получить максимальную производительность без чрезмерной задержки ввода-вывода, используя стратегию, заимствованную у сетевого планировщика CoDel. CoDel отслеживает наблюдаемую минимальную задержку сетевых пакетов и, если она превышает пороговое значение, начинает отбрасывать пакеты. Отказ от записи не одобряется в подсистеме ввода-вывода, но используется аналогичная стратегия: ядро ​​отслеживает минимальную задержку как чтения, так и записи, и, если она превышает пороговое значение, оно начинает уменьшать количество фоновой обратной записи. это делается. Это поведение было добавлено в 4.10; Axboe сказал, что были замечены довольно хорошие результаты.

WBT не требует переключения на новый блочный уровень blk-mq. Тем не менее, он не работает с планировщиками ввода-вывода CFQ или BFQ. Вы можете использовать WBT с планировщиками deadline / mq-deadline / noop / none. Я считаю, что он также работает с новым планировщиком ввода-вывода "kyber".

Помимо масштабирования размера очереди для контроля задержки, код WBT ограничивает количество фоновых запросов обратной записи как доля рассчитанного лимита очереди.

Конфигурация времени выполнения находится в /sys/class/block/*/queue/wbt_lat_usec.

Возможные варианты конфигурации сборки:

/boot/config-4.20.8-200.fc29.x86_64:CONFIG_BLK_WBT=y
/boot/config-4.20.8-200.fc29.x86_64:# CONFIG_BLK_WBT_SQ is not set
/boot/config-4.20.8-200.fc29.x86_64:CONFIG_BLK_WBT_MQ=y

Ваша постановка проблемы подтверждена на 100% автором WBT - молодец :-).

Блок [PATCHSET]: регулирование буферизованной обратной записи

С незапамятных времен наша обратная запись с фоновой буферизацией была отстойной. Когда мы выполняем обратную запись с буферизацией в фоновом режиме, это не должно иметь большого влияния на активность переднего плана. Это определение фоновой активности ... Но, насколько я помню, писатели с тяжелой буферизацией так себя не вели. Например, если я сделаю что-то вроде этого:

$ dd if=/dev/zero of=foo bs=1M count=10k

на моем ноутбуке, а затем попробуйте запустить Chrome, он в основном не запускается до завершения буферизованной обратной записи. Или для ориентированных на сервер рабочих нагрузок, когда установка большого RPM (или аналогичного) отрицательно влияет на чтение базы данных или синхронизирующую запись. Когда это происходит, люди кричат ​​на меня.

Результаты недавнего тестирования можно найти здесь:

https://www.facebook.com/axboe/posts/10154074651342933

Смотрите предыдущие сообщения для более подробного описания набора патчей.

Каков ваш средний показатель для Dirty в / proc / meminfo? Обычно это не должно превышать ваш / proc / sys / vm / dirty_ratio. На выделенном файловом сервере у меня dirty_ratio установлен очень высокий процент памяти (90), так как я никогда не буду его превышать. Ваша dirty_ration слишком низкая, когда вы попадаете в нее, все вылетает, поднимите.