У нас есть процессы, выполняющие фоновую запись больших файлов. Мы бы хотели, чтобы они оказали минимальное влияние на другие процессы.
Вот тест, реализованный на SLES11 SP4. Сервер имеет огромную память, что позволяет ему создавать 4 ГБ грязных страниц.
> dd if=/dev/zero of=todel bs=1048576 count=4096
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB) copied, 3.72657 s, 1.2 GB/s
> dd if=/dev/zero of=zer oflag=sync bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 16.6997 s, 0.0 kB/s
real 0m16.701s
user 0m0.000s
sys 0m0.000s
> grep Dirty /proc/meminfo
Dirty: 4199704 kB
Это мое исследование:
Вот мои вопросы:
см. Также
https://www.novell.com/support/kb/doc.php?id=7010287
ограничить сброс фона Linux (грязные страницы)
http://yarchive.net/comp/linux/dirty_limits.html
EDIT:[1292 visible) на том же устройстве существует файловая система ext2 . На этом девайсе вообще нет зависаний! Единственное влияние на производительность возникает во время очистки грязных страниц, когда синхронный вызов может занимать до 0,3 секунды, что очень далеко от того, что мы испытываем с нашей файловой системой ext3.
EDIT2: https://www.novell.com/support/kb/doc.php?id=7016100
Фактически под SLES11 dd открывает файл с
open("zer", O_WRONLY|O_CREAT|O_DSYNC, 0666) = 3
и O_DSYNC == O_SYNC!
Заключение :
Для моего случая использования мне, вероятно, следует использовать
dd if=/dev/zero of=zer oflag=dsync bs=512 count=1 conv=notrunc
В SLES11 выполнение oflag = sync действительно будет запускаться oflag = dsync независимо от того, что говорит strace.
Пару вещей, которые меня интересуют.
сначала создаем большой файл с fallocate
, а затем записываем в него.
Установка dirty_background_bytes намного ниже (скажем, 1Гб) и использование CFQ в качестве планировщика. Обратите внимание, что в этом тесте, возможно, было бы лучшим представлением, чтобы запустить малый в середине большого прогона.
Таким образом, для варианта 1, вы можете обнаружить, что вы избегаете всех семантик data=ordered
, так как выделение блока уже сделано (и быстро), так как оно было предварительно распределено через fallocate
, и метаданные устанавливаются перед записью. Было бы полезно проверить, действительно ли это так. У меня есть некоторая уверенность, хотя это улучшит производительность.
Для варианта 2 можно использовать ионику немного больше. Deadline явно быстрее, чем CFQ, хотя CFQ пытается организовать IO для каждого процесса так, чтобы вы нашли, что это дает вам лучшую долю IO через каждый процесс.
Я читал где-то (сейчас не могу найти источник), что dirty_background_ratio заблокирует запись против отдельного процесса коммитинга (фактически делая большой процесс медленнее), чтобы один процесс не проголодался, а все остальные. Учитывая то, как мало информации об этом поведении я могу найти сейчас, у меня меньше уверенности, что это сработает.
О: Я должен отметить, что fallocate
полагается на extents, и вам нужно будет использовать ext4.
Я отвечаю на свои вопросы, но если бы кто-нибудь мог предложить что-то лучшее, я был бы чрезвычайно признателен :)
имея 4 Гб грязной памяти в конце теста, я пришел к выводу, что планировщик ввода-вывода не был вызван в вышеуказанном тесте. Так ли это?
Это совершенно неправильно. Объем грязной памяти не является хорошим индикатором. Это можно легко доказать, просто запустив iostat и проверив, что при запуске dd oflag=sync происходит много записей.
Есть ли способ глубже изучить, что блокируется? Есть ли интересные счетчики для просмотра?
perf record -e 'jbd:*' -e 'block:*' -ag
Для более новых ядер, замените jbd на jbd2.
Есть идеи об источнике разногласий?
На самом деле для ext3 с data=ordered, поток journalling отвечает за промывку данных на диске. Промывка происходит в порядке записи. Частотой промывки можно управлять с помощью опции commit при монтировании файловой системы.
Интересный эксперимент: монтируйте файловую систему с помощью commit=60 и отключите поток обратной записи. При запуске первого dd он завершается за 2 с, и iostat показывает, что IO не генерировался!
При запуске второго dd с oflag=sync, все IO, генерируемые первым dd, смываются на диск.
мы подумываем либо об уменьшении значений dirty_ratio, либо о выполнении первого dd в синхронном режиме.
для записи оба решения дают хорошие результаты. Другая хорошая идея - поместить эти большие файлы в отдельную файловую систему (возможно, смонтированную с data=writeback)
Это не связано специально с SLES11 или старыми ядрами. Такое же поведение наблюдается на всех ядрах, которые я пробовал
.Это ожидаемое поведение ext3: В этой файловой системе синхронная запись блока до тех пор, пока все предыдущие грязные блоки не будут записаны на диск. Именно по этой причине разработчики так полностью пропустили все синхронизированные записи за последние годы.
Ext4, XFS, ZFS и BTRFS в этом отношении гораздо лучше. Учитывая, что ext4 более или менее подменяет ext3, вам действительно стоит обновить свою файловую систему.
.