Есть у нас сервер, одна из основных задач которого - получать множество счетчиков по сети, опрашивая разные устройства, сохранять значения счетчиков в файлах RRD и по требованию рисовать графики, всего более 2500 файлов RRD.
На сервере работает два параллельных независимых процесса. Один раз в 5 минут опрашивает множество устройств в сети и за счет высокого параллелизма успевает опросить 2500+ устройств за одну минуту, снимая с каждого устройства одним запросом по нескольку десятков счетчиков и сохраняя эти данные во временных файлах на файловой системе.
Второй стартует тоже раз в 5 минут, но со смещением по времени относительно первого процесса и перемещает данные из временных файлов в базы RRD. До недавнего времени сервер работал под управлением FreeBSD 8.4-STABLE, но в связи с окончанием поддержки (EoS/EoL) восьмой ветки операционная система была обновлена до FreeBSD 9.3-STABLE. До обновления один полный цикл работы этого второго процесса занимал не более минуты, а после обновления он стал работать в 6 раз медленнее. Да и вообще, резкое замедление и уменьшение "отзывчивости" дисковой подсистемы стало заметно невооруженному глазу.
Довольно скоро обнаружил, что всё дело в системном параметре sysctl vfs.read_max, задающем предел для опережающего чтения для UFS в блоках файловой системы. В восьмой версии его значение по умолчанию 8, а в девятой 64. То есть, FreeBSD 8 при чтении одного блока из базы RRD может нагрузить диск чтением восьми блоков, засунув "лишние" данные в кеш, а FreeBSD 9 может нагрузить диск в восемь раз больше плюс занять больше места в кеше. Это может ускорить работу с файлами, когда реально требуется читать файлы целиком или большими кусками.
Но при обновлении RRD-файла выполняется чтение только небольшой части файла и ядерное опережающее чтение впустую нагружает диск и кеш ненужной работой. Уменьшил предел обратно до 8 блоков (старый дефолт) и производительность возрасла в 6 раз, вернувшись к старым значениям.
древний баг fsck_ffs
2011-08-31 23:59Недавно во время экспериментов одна из файловых систем FreeBSD на домашнем десктопе у меня повредилась так, что в одном из подкаталогов появился файл с именем нулевой длины, что недопустимо для UFS2: системные вызовы ядра не обрабатывают такие файлы. Оказалось, что fsck_ffs не проверяет эту проблему и поэтому рапортует, что файловая система чиста. Удалить каталог с таким файлом невозможно и т.д.
Пришлось запатчить fsck_ffs, добавив нужную проверку:
http://www.freebsd.org/cgi/query-pr.cgi?pr=160339
Баг сидит в коде FreeBSD с первоначального импорта исходников BSD 4.4 Lite более 17 лет назад. В коде NetBSD и OpenBSD этой проверки тоже нет.
Update: в девятой ветке исправлено 2 сентября и релиз 9.0 будет уже с исправлением. В 7.4-STABLE и в 8.2-STABLE исправлено 16 сентября.
buildworld
2011-06-14 01:48Повторил старый тест на сегодняшней FreeBSD 8.2-STABLE/UFS.
На двухъядерной домашней системе создал /dev/md0 в 2G размером, смонтировал (async) в /mnt/tmp, скопировал туда /usr/src, создал там же obj и tmp и запустил:
# cd /mnt/tmp/src; time env TMPDIR=/mnt/tmp/tmp MAKEOBJDIRPREFIX=/mnt/tmp/obj make -j3 MODULES_WITH_WORLD=yes buildworld
...
real 61m8.607s
user 99m57.180s
sys 11m30.844s
Эффективность распараллеливания на два ядра более 91%.
Затем то же самое сделал без md:
real 62m21.302s user 100m22.833s sys 12m6.297s
Разница — 1 минута и 12.7 секунды. Как и на 7.0, морочиться с созданием RAM-диска нет смысла, FreeBSD достаточно хорошо кеширует UFS.