MemoryHigh замедляет сервис: читаем memory.events до аварии

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

Найти реальную группу

systemctl show worker.service -p ControlGroup -p MemoryCurrent -p MemoryHigh -p MemoryMax
cat /sys/fs/cgroup/system.slice/worker.service/memory.events
cat /sys/fs/cgroup/system.slice/worker.service/memory.stat

Пути во второй и третьей строках — пример для ControlGroup=/system.slice/worker.service; подставьте фактическое значение первой команды. Сценарий относится к cgroup v2. Не смешивайте его файлы с интерфейсом старой иерархии. Проверяйте также ограничения родительских slices: свободная память хоста не отменяет политику группы.

В memory.events важны приращения high, max, oom и oom_kill. high сообщает о случаях ограничения и освобождения при превышении высокой границы. max показывает попытки пересечь жёсткую границу, а oom_kill — уничтоженные OOM-механизмом процессы. Один рост max ещё не равен гибели процесса. Формат и иерархический учёт описаны в интерфейсе cgroup v2.

Поймать связь с задержками

Сохраните значения перед воспроизводимым заданием и сразу после него. Например, high вырос с 15 до 140, а oom_kill остался нулевым. Это направляет расследование к reclaim и рабочему набору, а не к поиску причины исчезновения PID. Добавьте memory.pressure той же группы: так видно, сопровождается ли рост событий реальными потерями времени.

memory.stat помогает разделить anon, file и kernel. Большой file может означать активно используемый файловый кэш; большой anon — память приложений и анонимных отображений. Снижение всех лимитов в ответ на большую цифру усиливает давление. Нужна связь категории с работой: сколько задач выполнялось, какой объём данных они держали и когда освобождали.

Менять одну границу за раз

MemoryHigh удобно использовать как управляемую границу давления, MemoryMax — как более жёсткий предел. Значения выбирают с учётом соседних служб и полного бюджета машины. Если группа получает больше памяти, проверьте после изменения также системный PSI и память других групп. Иначе локальное ускорение скроет перенесённую проблему.

Другой вариант — уменьшить число одновременно обрабатываемых заданий. Он особенно полезен, когда каждое задание держит большой независимый набор данных. Для проверки возьмите одинаковый вход, сравните длительность, пиковое MemoryCurrent и приращение high. Выбирайте режим по общему времени завершения очереди, а не только по скорости одной задачи.

Как выглядит ограничение без уничтожения процесса

В условном снимке перед заданием memory.current равен 1,6 ГиБ, memory.high — 2 ГиБ, memory.max — 3 ГиБ. Через минуту current колеблется около 2,1 ГиБ, high увеличился на 125, oom_kill не изменился, а memory.pressure some avg10 достиг 12. Это согласуется с потерями времени при освобождении памяти, хотя жёсткий предел ещё не достигнут.

Теперь уменьшите на стенде параллелизм с восьми заданий до четырёх. Если current стабилизировался на 1,5 ГиБ, high за тот же интервал не растёт и очередь в целом завершается быстрее, найден практичный режим. Если очередь стала вдвое дольше, сравните стоимость дополнительной памяти с требованиями к окну обработки. Выбор подтверждается временем всей работы, а не только исчезновением событий.

Что сохранить в разборе инцидента

Оставьте значения лимитов, путь группы, исходные и конечные счётчики, размеры нагрузки и измеренную длительность. Счётчики могут исчезнуть при пересоздании cgroup, поэтому после перезапуска нельзя механически вычитать старое значение. Такой отчёт объясняет и замедление, и эффект изменения.

Курс «Linux и Bash для DevOps-инженеров» даёт связанную практику с процессами, systemd и диагностикой памяти. Откройте программу, чтобы перейти от отдельных ресурсных файлов к сопровождению сервиса и собственному порядку проверки подобных сбоев.

Ещё по теме

Продолжить на практике

  • Linux и Bash для DevOps-инженеров ↗

    Linux для работы с серверами: процессы, права, systemd, сеть, диски и логи. Автоматизируйте повседневные задачи на Bash и разберите типичные сбои сервиса — от занятого порта до переполненного диска.