systemd-journald тратит минимум 55 КБ на одну строку лога

systemd-journald тратит минимум 55 КБ на одну строку лога

Пользователь XANi завёл в GitHub-репозитории systemd issue #40262 (открыт 3 января 2026 года): на его виртуальной машине с Debian 13 (systemd 257.9, ядро 6.12.57) служба systemd-journald создавала около 50 IOPS (операций ввода-вывода в секунду) дисковой активности, хотя реальный поток логов, вывод haproxy, составлял всего две строки в секунду; файловая система, XFS. По словам XANi, это та же проблема, что уже поднималась в issue #15292, но, как он считает, тогда её закрыли без внятного объяснения; его ожидание, что объём записи логов через journald должен быть сопоставим с классическим syslog, а не на порядки больше.

Семь месяцев спустя, в начале августа, участник обсуждения ValdikSS решил измерить проблему инструментально. Он выделил под /var/log/journal отдельное loop-устройство с файловой системой ext4, отключил сжатие journald (Compress=no), выставил SyncIntervalSec=10s и параллельно логировал два независимых счётчика: сколько байт реально пишет блочное устройство (по счётчику ядра для loop-диска) и сколько именно приписывает journald его собственный cgroup-счётчик io.stat. Результат: одна запись в журнале для тестовой строки лога (logger -p info test), включая все служебные поля, весит около 752 байт. Но физически на диск при этом уходит минимум 55 КБ, и для одной такой строки, и для пакета из десяти одинаковых строк подряд: минимальный порог записи в обоих случаях один и тот же. За 14 отдельных строк лога суммарная запись на устройство составила 386 КБ по счётчику блочного устройства, из которых 319 КБ ValdikSS сумел явно отнести на journald через cgroup-учёт.

Для сравнения он смоделировал классический syslog: обычное дописывание в текстовый файл с той же надёжностью, fdatasync и fsync после каждой строки. На три такие строки ушло всего 21 КБ, заметно меньше, чем даже минимум journald. Похожий эксперимент на btrfs (том с включённой опцией chattr +C, отключающей copy-on-write) показал сопоставимые или даже большие разовые приросты записи на событие, хотя итоговую суммарную цифру для btrfs, в отличие от ext4, ValdikSS не подводил.

По ходу разбора всплыла и вторая деталь: ValdikSS ожидал, что journald буферизует записи в памяти в течение SyncIntervalSec и лишь потом пишет на диск, но измерения показали обратное, journald сразу пишет каждое новое сообщение в постоянный файл журнала, а SyncIntervalSec управляет только частотой вызова fsync, а не тем, когда данные вообще попадают на диск. Сам XANi считает, что дело не в mmap-записи как таковой, а в формате хранения: каждая запись в журнале дублирует boot ID и другую повторяющуюся информацию, а сам файл не индексирован так, чтобы запись или чтение были дешёвыми.

Отдельно высказался разработчик amluto: много лет назад он сам делал базу данных, дописывающую лог через mmap, и, оглядываясь назад, называет это решение ошибочным, по его словам, обычный pwrite оказался бы куда эффективнее; он спросил, может ли кто-то объяснить, почему journald вообще выбрал именно mmap-запись.

Ещё один пользователь, joaociocca, столкнулся со схожей проблемой независимо, на реальной работающей системе: он ловил необъяснимые просадки производительности и с помощью режима накопления в iotop обнаружил, что journald записал на диск почти 7 ГБ данных за 15 минут, и почти 11 ГБ за 22 минуты; в это время в журнале многократно повторялась строка о том, что служба «сбрасывает кэш из-за нехватки памяти» (Under memory pressure, flushing caches).

На момент последних комментариев (13, 14 августа) issue остаётся открытым: ни один мейнтейнер systemd/journald в обсуждении не появился, а сами измерения, результат тестов отдельных участников на своих конфигурациях (VM на XFS у XANi; loop-устройство на ext4 и отдельный том btrfs у ValdikSS), а не официальный бенчмарк по умолчанию для всех дистрибутивов и файловых систем. Точная техническая причина перерасхода тоже не подтверждена: версии участников расходятся между форматом хранения, самим подходом mmap и, по стороннему замечанию, процитированному в последнем комментарии, особенностями работы «крупных folio» в ядре Linux, из-за которых, как утверждается, страдает запись через mmap на разных файловых системах в целом.

Ключевые факты

  • Баг начался с конкретики: VM на Debian 13 (systemd 257.9) показывала около 50 IOPS дисковой нагрузки при потоке всего в 2 строки лога в секунду от haproxy на файловой системе XFS.
  • ValdikSS с помощью отдельного loop-устройства на ext4 и cgroup-счётчиков самого journald показал: одна запись в журнале для тестовой строки лога весит около 752 байт, но физически на диск уходит минимум 55 КБ, и для одной строки, и для пакета из десяти.
  • Для сравнения тест на трёх строках обычного текстового лога с fdatasync и fsync после каждой строки дал всего 21 КБ, заметно меньше даже минимума journald.
  • На 14 строк лога суммарная запись на устройство составила 386 КБ по счётчику блочного устройства, из них 319 КБ отнесено на сам journald через cgroup io.stat.
  • Похожий (или больший) перерасход на событие ValdikSS зафиксировал и на btrfs; независимо от него пользователь joaociocca поймал на реальной системе почти 7 ГБ записи от journald за 15 минут и почти 11 ГБ, за 22 минуты.

Почему это важно

Служба journald, стандартный компонент systemd для логирования, который работает по умолчанию на большинстве современных Linux-дистрибутивов. Если она действительно физически пишет на диск на порядок больше данных, чем весит сам текст лога, это не абстрактная неэффективность: лишняя запись означает лишний износ SSD, лишнюю нагрузку на IOPS, особенно чувствительную для виртуальных машин и облачных дисков, где IOPS часто лимитированы или тарифицируются, и риск, что диск незаметно станет узким местом там, где на него никто не грешил. Обсуждение переводит смутную жалобу «journald слишком много пишет» в измеримые числа, минимум 55 КБ на одну строку лога на ext4 против 21 КБ у обычного текстового лога с той же надёжностью, и в конкретный пример, где это уже проявилось на живой системе как многогигабайтная запись за считаные минуты.

Кому это важно

В первую очередь, системным администраторам и DevOps/SRE-инженерам на Linux с systemd (в обсуждении фигурируют Debian и Fedora), особенно тем, кто разворачивает такие системы на виртуальных машинах или в облаке, где IOPS ограничены или тарифицируются. Особенно актуально для систем с активным потоком логов, в исходном репорте это прокси-сервер на haproxy. Полезно и тем, кто уже ловил необъяснимые просадки производительности и грешил на диск или сеть, не подозревая journald, как в случае с joaociocca. Наконец, это прямой вопрос к мейнтейнерам самого systemd/journald, которые в обсуждении пока не появились.

Как это применить

Из треда можно вынести практические полумеры, а не готовое решение. Если хранить логи между перезагрузками не обязательно, участник birdie-github предлагает переключить journald в режим Storage=volatile в секции [Journal] конфигурации, тогда журнал живёт в памяти, а не на диске. В начале обсуждения предлагали отключить сжатие (Compress=no) как первый диагностический шаг, но у XANi это не дало заметной разницы, от лишней записи это не спасает. ValdikSS отдельно указывает на монтирование ext4 с опцией lazytime, которая снижает накладные расходы на обновление времени доступа к файлам, но, по замечанию XANi, это не лечит саму проблему: большая часть активных файлов журнала и так свежая и уже подпадает под стандартный relatime. Официального патча или подтверждённого срока исправления на момент обсуждения нет, все перечисленные шаги снимают отдельные симптомы, а не устраняют перерасход в самом формате journald.

Можно ли доверять

Ключевые цифры, не оценка на глаз: ValdikSS собирал их через собственный python-скрипт, который параллельно сверял счётчик записи блочного устройства (loop-диска) со счётчиком cgroup именно службы journald, и опубликовал сам скрипт в комментарии, методику можно проверить и повторить. Второй, независимый пример, joaociocca с почти 7, 11 ГБ за 15, 22 минуты, получен на реальной работающей системе, а не в синтетическом тесте, что снижает риск, что дело только в искусственных условиях эксперимента. При этом стоит учитывать: и первый баг-репорт (VM на XFS), и подробный замер (loop-устройство на ext4, отдельно, том btrfs), это тесты отдельных участников на своих конкретных конфигурациях, а не официальный бенчмарк systemd по умолчанию для всех дистрибутивов и файловых систем. Спустя более семи месяцев после открытия issue ни один мейнтейнер systemd/journald в обсуждении не появился, официального ответа или срока исправления нет. Точная техническая причина перерасхода тоже не подтверждена: XANi считает дело в самом формате журнала (дублирование boot ID, отсутствие нормальной индексации), amluto, в самом подходе с mmap-записью, а участник KyleSanderson в последнем на момент обсуждения комментарии приводит стороннюю цитату с Reddit со ссылкой на разработчика файловой системы bcachefs о том, что от перерасхода при mmap-записи страдают вообще все файловые системы из-за механизма «крупных folio» в ядре Linux, и предлагает отключать folio как временную меру. Все три версии, гипотезы участников обсуждения, ни одна не подтверждена ответственными за код systemd или ядро. Наконец, характеристика XANi, что похожий issue #15292 в своё время «закрыли без внятной причины», его личная оценка: какая причина была названа тогда на самом деле, в источнике не зафиксировано.

Риски и подводные камни

Экстраполировать цифры «в лоб» на любую систему не стоит: 55 КБ, 21 КБ, 386/319 КБ и результаты по btrfs, это показатели на конкретной настройке ValdikSS (Compress=no, SyncIntervalSec=10s, отдельное loop-устройство), а не универсальная константа для journald вообще; в исходном репорте XANi на файловой системе XFS зафиксирована не эта же величина в килобайтах, а нагрузка в IOPS, это другая единица измерения той же проблемы, и одно число из другого напрямую не выводится. Ни один из предложенных обходных путей не устраняет причину: Storage=volatile жертвует сохранностью логов между перезагрузками, отключение сжатия не помогло XANi лично, а lazytime, по его же оценке, снимает не основную часть проблемы. Официального фикса или заявления мейнтейнеров нет, так что похожая более ранняя история, issue #15292, которую XANi называет закрытой «без внятной причины», хотя это его личная оценка, а не задокументированный ответ мейнтейнеров, вполне может повториться и с этим обращением.

«Формат хранения на диске крайне расточительный и многословный, например, каждое сообщение повторяет boot ID и массу другой задублированной информации. Разумной индексации тоже нет, поэтому дорого и писать, и читать.»

— XANi