Загрузка...

Сжатие оперативной памяти в Linux: ZRAM и zswap против OOM Killer и дискового I/O

Сжатие оперативной памяти в Linux: ZRAM и zswap против OOM Killer и дискового I/O

Классический дисковый swap на сервере или рабочей станции с Linux — это гарантированная деградация производительности в момент, когда RAM подходит к концу. Как только ядро начинает активно сбрасывать анонимные страницы на NVMe или SATA SSD, система упирается в I/O wait, latency запросов взлетает на порядки, а базы данных и фоновые очереди встают колом еще до того, как сработает OOM Killer. При этом постоянный сброс мусора в дисковый swap ускоренно расходует ресурс перезаписи ячеек памяти накопителя (TBW).

Современное ядро Linux предлагает встроенную альтернативу механической записи на накопитель — сжатие страниц памяти «на лету» в оперативной памяти с помощью модулей ZRAM и zswap. Разберем их архитектурные различия, подкапотное устройство аллокаторов и алгоритмов компрессии, а также боевые конфигурации для production-окружения.

Архитектурный водораздел: ZRAM vs zswap

Хотя оба механизма используют алгоритмы компрессии в оперативной памяти, они спроектированы под диаметрально противоположные сценарии и работают на разных уровнях стека подсистемы виртуальной памяти ядра.

Критерий ZRAM (Compressed RAM block device) zswap (Compressed swap cache)
Тип сущности Виртуальное блочное устройство (/dev/zram0) Внутриядерный кэш перед физическим диском
Дисковый swap Не требуется вовсе (полная автономность) Обязателен (swap-раздел или swap-файл)
Вытеснение (Eviction) По умолчанию сжатые страницы не сбрасываются на диск При исчерпании пула сбрасывает старые страницы на диск
Поддержка гибернации Нет (содержимое RAM теряется при выключении питания) Да (через сброс на связанный физический swap)
Оптимальный сценарий VPS без дискового swap, контейнеры, микро-SaaS, десктоп High-load серверы с терабайтами медленного NVMe/SSD swap

Важное архитектурное правило: никогда не включайте ZRAM и zswap одновременно на одном и том же узле под одинаковые задачи. В такой конфигурации zswap попытается сжимать страницы, которые затем направятся на виртуальное устройство ZRAM, где будут повторно сжиматься. Это приводит к двойному расходу процессорных тактов и снижению эффективности компрессии.

Алгоритмы сжатия и ядерные аллокаторы

Эффективность сжатия оперативной памяти упирается не столько в коэффициент компрессии, сколько в соотношение скорости сжатия/распаковки к задержке ядра:

  • zstd (Zstandard): промышленный стандарт де-факто. Дает степень сжатия 2.7x–3.2x на типичных текстовых структурах, структурах PHP-FPM сессий и SQL-кэша. Идеальный баланс между скоростью декомпрессии и экономией RAM.
  • lz4 / lzo-rle: экстремально быстрые алгоритмы. Коэффициент сжатия скромнее (около 2.0x–2.3x), но накладные расходы по CPU минимальны. Подходит для высоконагруженных узлов с утилизацией процессора выше 80%.

Для упаковки сжатых кусков разного размера внутри ядра используются специализированные аллокаторы пула (zpool):

  • zsmalloc (используется в ZRAM): оптимизирован для экстремально плотной упаковки объектов разного размера с минимальной фрагментацией.
  • z3fold / zbud (используется в zswap): упаковывает до 3 (или 2) сжатых страниц в один физический фрейм 4 КБ.

Развертывание ZRAM через systemd-zram-generator

Штатный и наиболее отказоустойчивый способ настройки ZRAM в современных дистрибутивах (Ubuntu 22.04/24.04, Debian 12, Fedora) — пакет systemd-zram-generator. Он генерирует виртуальное блочное устройство на этапе инициализации systemd без громоздких bash-скриптов в cron.

1. Установка генератора

sudo apt update && sudo apt install -y systemd-zram-generator

2. Конфигурация пула

Создайте конфигурационный файл /etc/systemd/zram-generator.conf:

[zram0]
# Размер пула относительно физической RAM (0.5 = 50% от объема RAM)
zram-size = ram / 2

# Алгоритм компрессии ядра
compression-algorithm = zstd

# Наивысший приоритет, чтобы ядро отдавало предпочтение ZRAM перед диском
swap-priority = 100

3. Применение и запуск

sudo systemctl daemon-reload
sudo systemctl start /dev/zram0

4. Верификация состояния

Убедитесь, что блочное устройство активно и ядро направляет туда трафик:

zramctl
swapon --show

Вывод zramctl наглядно покажет DISKSIZE (виртуальный лимит), DATA (несжатый объем полученных страниц) и COMPR (реальный объем памяти, занятый сжатыми блоками в RAM).

Настройка zswap в качестве кэша дискового раздела

Если на сервере уже есть физический NVMe/SSD swap-раздел и требуется гибернация либо защита от переполнения памяти при пакетной обработке тяжелых медиафайлов, оптимален zswap.

1. Активация через параметры GRUB

Откройте /etc/default/grub и дополните строку GRUB_CMDLINE_LINUX_DEFAULT:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash zswap.enabled=1 zswap.compressor=zstd zswap.zpool=zsmalloc zswap.max_pool_percent=25"

Параметр zswap.max_pool_percent=25 жестко ограничивает аппетит zswap: под сжатый кэш будет выделено не более 25% от физической оперативной памяти. Все излишки ядро прозрачно сбросит на физический диск.

2. Обновление загрузчика и перезагрузка

sudo update-grub
sudo reboot

3. Мониторинг эффективности zswap на лету

Статистика работы zswap доступна напрямую из виртуальной файловой системы /sys/kernel/debug/zswap/:

sudo grep -r . /sys/kernel/debug/zswap/

Ключевой показатель — stored_pages (число страниц в сжатом пуле) и reject_compress_poor (страницы, которые ядро отказалось сжимать из-за отрицательного коэффициента сжатия).

Тюнинг sysctl для эффективного сжатия

По умолчанию ядро неохотно обращается к swap до тех пор, пока не исчерпается весь дисковый кэш (page cache). Для ZRAM и zswap логику вытеснения страниц следует агрессивно изменить: сжатие в RAM в сотни раз дешевле сброса на диск, поэтому анонимные неактивные страницы выгоднее сжимать заблаговременно.

Добавьте следующие параметры в /etc/sysctl.d/99-zram.conf:

# Агрессивно вытесняем неактивные страницы в сжатый пул (по умолчанию 60)
vm.swappiness = 150

# Снижаем агрессивность сброса файлового кэша dentry/inode
vm.vfs_cache_pressure = 50

# Предотвращаем преждевременные задержки страниц в буферах
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125

Примените настройки без перезагрузки:

sudo sysctl --system

При таком тюнинге система на 4–8 ГБ оперативной памяти получает эффективный объем порядка 10–14 ГБ под рабочие процессы (Docker-контейнеры, базы данных, воркеры очередей), сохраняя нулевой I/O wait накопителя.

Промпт для AI-агентов: автоматический аудит и внедрение ZRAM

Чтобы не настраивать параметры подкачки вручную на каждом сервере или рабочей машине, задачу можно делегировать AI-агенту (Claude Code, Cursor, OpenCode, Hermes). Готовый системный промпт инструктирует агента безопасно оценить текущую конфигурацию подсистемы памяти хоста и сформировать запрос на оптимизацию:

Ты — Linux DevOps-инженер. Твоя задача: проверить текущую подсистему памяти и swap, после чего оптимизировать её с помощью ZRAM,
 сохранив дисковый swap как аварийный fallback.

   1. Аудит хоста (только чтение):
      - Выполни: `free -h`, `swapon --show`, `lscpu | grep -E "Model name|CPU\(s\):"`, `cat /proc/sys/vm/swappiness`.
      - Проверь, активен ли уже ZRAM или zswap: `zramctl`, `cat /sys/module/zswap/parameters/enabled 2>/dev/null`.

   2. Логика принятия решений:
      - Если ZRAM уже активен с наивысшим приоритетом — покажи `zramctl` и заверши аудит без изменений.
      - Если ZRAM отсутствует: настрой его через `systemd-zram-generator` с размером `ram / 2`, алгоритмом `zstd` и приоритетом `100`.
      - Существующий дисковый swap (файл или раздел) НЕ удалять — он остаётся резервом при исчерпании RAM и ZRAM.

   3. Применение конфигурации:
      а) Установка генератора (по дистрибутиву: `apt install systemd-zram-generator` / `dnf` / `pacman`).
      б) Конфиг `/etc/systemd/zram-generator.conf`:
         [zram0]
         zram-size = ram / 2
         compression-algorithm = zstd
         swap-priority = 100
      в) Тюнинг ядра `/etc/sysctl.d/99-zram.conf`:
         vm.swappiness = 150
         vm.watermark_boost_factor = 0
         vm.watermark_scale_factor = 125
         vm.page-cluster = 0
      г) Активация:
         `sudo systemctl daemon-reload && sudo systemctl start systemd-zram-setup@zram0.service && sudo sysctl --system`

   4. Верификация:
      - Проверь `swapon --show` и `zramctl`.
      - Убедись, что `/dev/zram0` активен с `PRIO=100`, а весь дисковый swap имеет более низкий приоритет (< 0).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *