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

26

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

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

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

Коркман
источник
Может быть, это был бы хороший вопрос для отправки в список рассылки ядра Linux vger.kernel.org/vger-lists.html#linux-kernel
Какой планировщик ввода-вывода вы используете?
3dinfluence
Пробовал разные (cfq, дедлайн), но я думаю, что они работают надежно только тогда, когда кэш записи с резервным питанием от батареи не включен. Как один дисковый массив, я ем 1 ГиБ данных на скорости шины PCIe (RAM), а затем врезаюсь в реальность. Несколько секунд ноль ввода-вывода для всех LUN. Дросселирование приливов (по крайней мере, фоновых) к грубой оценке фактической скорости устройства решило бы эту проблему перегрузки.
korkman
1
Недавно мне стало известно о том, что / sys / block / sdX / queue / nr_requests является основной настраиваемой. Уменьшение его до минимума (= 4 в моем случае) значительно увеличивает задержку одновременной загрузки: Sysbench fsync случайных записей в секунду подскочил с 4 (!) До 80-90 при записи на скорости шины с помощью dd. Незагруженная производительность кажется неизменной. Планировщики все одинаковы, ноуп или срок кажется оптимальным. Это может быть верно для большинства конфигураций BBWC.
korkman

Ответы:

20

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

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

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

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

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

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


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

Протестировано при установке ddнулей на диск, sysbench продемонстрировал огромный успех , увеличив 10 потоковых записей fsync при 16 кБ с 33 до 700 операций ввода-вывода в секунду (предел простоя: 1500 операций ввода-вывода в секунду) и одного потока от 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 ГБ 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 с 15 МБ 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 с 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

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

Коркман
источник
Какова ваша методология для получения части «15 МБ для dirty_buffers оптимальна»?
Марцин
1
Методом проб и ошибок. Например, поменяйте половину суммы в следующий раз и т. Д., Пока у меня не останется всего 15 МБ и ОК IOPS. Текущее ядро ​​3.2 может вести себя совсем иначе, кстати.
korkman
2
Просто хотел сказать спасибо, что поставил меня на правильный путь. Были некоторые похожие проблемы с узлом XenServer. Оказалось, что PHP-FPM / APC-кеш вызывает грязные страницы. Настройка модели кэш-памяти APC решила проблему для нас. DiskIO снизился с 20% до 0.
jeffatrackaid
По логике он dirty_bytesдолжен быть достаточно высоким, чтобы не останавливать процессоры во время записи процессов, если процесс пишет в среднем с пропускной способностью устройства. Если код вашего приложения выполняет циклы огромных вычислений с последующей записью огромного количества данных, оптимизировать его будет очень сложно, поскольку средние значения за короткое время сильно отличаются от средних значений за долгое время. Правильным решением было бы настроить dirty_bytesпараметры, специфичные для процесса, но Linux не поддерживает такую ​​вещь, насколько я знаю.
Микко Ранталайнен,
3

Несмотря на то, что настройка параметров ядра остановила проблему, на самом деле, возможно, проблемы с производительностью были результатом ошибки контроллера 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.

sa289
источник
1
Вау, спасибо за ваш вклад. Хотя это было не так для меня, вы даете мне еще одну причину, чтобы вообще избежать HW RAID и перейти к настройкам только HBA. HW RAID по-прежнему имеет преимущество BBWC, но с такими вещами, как bcache, движущимися в ядро, даже это исчезает. Положительной стороной для HW RAID является именно тот тип ошибок прошивки, который вы описываете. У меня была другая система с настройкой DRBD и высокой нагрузкой ввода-вывода, вызывающей перезагрузку прошивки, так что это не редкость (возможно, именно эта ошибка).
korkman
1

Ядро, в состав которого входит «WBT»:

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

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

WBT не требует переключения на новый блочный уровень blk-mq. Тем не менее, он не работает с планировщиками ввода-вывода CFQ или BFQ. Вы можете использовать WBT с планировщиками дедлайн / 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

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

sourcejedi
источник
Я рад видеть, что проблема распознается и решается внутри ядра. Имейте в виду, что blk-mq довольно новый и, возможно, еще не настолько зрелый .
Коркман
@ korkman вздох, я думаю, я искажу цитату, чтобы избежать ложного смысла. Я согласен, что это материал, который был добавлен в последние пару лет, могут быть ухудшения производительности или еще хуже. AFAIR сопровождающий отклоняет исправление повреждения данных в том смысле, что это случайность. Если вы используете версии ядра, в которых был разработан blk-mq, можно утверждать, что использование «устаревшего» блочного слоя позволит избежать ошибок. Исправленная мной ошибка приостановки была ошибкой, возникшей в blk-mq, затем она была подвергнута рефакторингу или что-то и затронуло оба. github.com/torvalds/linux/commit/1dc3039bc87a
sourcejedi
0

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

Люк
источник
Проблема не в том, что процессы блокируются при нажатии dirty_ratio. Я в порядке с этим. Но «фоновый» процесс записи грязных данных на диски безжалостно заполняет очереди и снижает производительность IOPS. Я думаю, это называется IO голодание. На самом деле, установка dirty_ratio_bytes на очень низкое значение (например, 1 МБ) очень помогает, потому что очистка произойдет почти сразу, а очереди останутся пустыми. Недостатком может быть низкая пропускная способность для последовательного, но это нормально.
Коркман
Вы отключили все лифты? Что еще ты подправил из ванильной системы?
Люк
1
Смотри мой ответ. Конец истории должен был удалить грязное кеширование и оставить эту часть контроллеру HW. Лифты не имеют никакого отношения к HW write-cache. Контроллер имеет свои собственные алгоритмы лифта, поэтому наличие любого лифта в программном обеспечении только увеличивает издержки.
Коркман
Elevevator в программном обеспечении является компромиссом: жертвуйте временем ожидания для улучшения пропускной способности. Например, представьте 100 000 операций записи в очередь программного обеспечения, представленную в случайном порядке; если программный лифт может упорядочить эти операции с использованием огромного буфера, это может привести к тому, что на устройство будут отправляться только запросы на 5 Кб. Однако в результате задержка должна быть увеличена на 100 тыс. Операций, поскольку может случиться так, что первые 2 КБ операции и последние 1 КБ операции фактически находятся рядом друг с другом на устройстве. Без дополнительной задержки объединить их будет невозможно.
Микко Ранталайнен,