Category: еда

chuck

Не всем йогурты одинаково полезны

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