Классический дисковый 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).