Подробный гайд по мониторингу и отладке zswap в Linux
Мониторинг zswap — отличная задача, которая позволяет понять, насколько эффективно работает промежуточный кэш сжатия и не деградирует ли производительность системы из-за постоянного сброса (write-back) страниц на медленный диск.
Ниже представлен подробный гайд по сбору всех необходимых метрик с использованием vmstat, debugfs и файловых интерфейсов ядра.
Подготовка: Проверка окружения
Для сбора метрик вам понадобятся права root. Убедитесь, что zswap включен и файловая система debugfs смонтирована.
# Проверка, включен ли zswap
cat /sys/module/zswap/parameters/enabled
# Должно быть: Y
# Проверка, смонтирована ли debugfs
mount | grep debugfs
# Если нет, монтируем: mount -t debugfs none /sys/kernel/debug
Примечание:
В некоторых новых версиях ядра (5.x/6.x) статистика zswap может быть перенесена из /sys/kernel/debug/zswap/ в /sys/kernel/mm/zswap/ или /sys/kernel/debug/zswap/. Если путь не находится, используйте find /sys -type d -name zswap.
1. Сколько памяти сейчас сжато в zswap
Чтобы понять текущее состояние кэша, нам нужно посмотреть, сколько страниц хранится в сжатом виде и какой объем физической памяти они занимают.
Используем /sys/kernel/debug/zswap/:
# Количество страниц, находящихся сейчас в zswap
cat /sys/kernel/debug/zswap/stored_pages
# Общий размер сжатого пула в байтах (физическая память, занятая под сжатые данные)
cat /sys/kernel/debug/zswap/pool_total_size
Как посчитать коэффициент сжатия (Compression Ratio):
Коэффициент сжатия показывает, насколько эффективно работает алгоритм (например, zstd или lz4).
Формула: (stored_pages * 4096) / pool_total_size
Быстрая команда для расчета:
STORED=$(cat /sys/kernel/debug/zswap/stored_pages)
SIZE=$(cat /sys/kernel/debug/zswap/pool_total_size)
if [ "$SIZE" -gt 0 ]; then
echo "scale=2; ($STORED * 4096) / $SIZE" | bc
else
echo "zswap пуст"
fi
Нормальный коэффициент сжатия обычно находится в диапазоне от 2.0 до 3.5.
2. Сколько страниц было вытеснено на диск (Evictions / Write-backs)
Вытеснение на диск (write-back) происходит, когда пул zswap заполняется, и ядру приходится сбрасывать старые сжатые страницы на реальный swap-устройство (диск), чтобы освободить место для новых. Это самая "медленная" операция, и ее нужно минимизировать.
Используем /sys/kernel/debug/zswap/:
# Количество страниц, которые были записаны обратно на диск (вытеснены)
cat /sys/kernel/debug/zswap/written_back_pages
Как интерпретировать:
- Если
written_back_pagesпостоянно растет в течение длительного времени, значит, размера пулаzswap(параметрzswap.max_pool_percent, по умолчанию 20% от RAM) не хватает, и система активно использует медленный дисковый swap.
3. Сколько страниц успешно прочитано из кэша (Hits / Swaps In)
Чтобы понять, сколько раз zswap спас ситуацию и отдал данные из своего кэша (не заставляя читать с диска), мы обращаемся к vmstat и /proc/vmstat.
Используем vmstat и /proc/vmstat:
# Просмотр всех метрик swap, связанных с zswap
grep zswap /proc/vmstat
# Или через vmstat
vmstat -s | grep -i zswap
Ключевые метрики:
zswpin— это и есть количество страниц, успешно прочитанных из кэша zswap (Cache Hits). Это данные, которые вернулись из сжатого кэша в RAM.zswpout— количество страниц, которые были записаны из RAM в кэш zswap.
Как посчитать Hit Rate (Процент попаданий в кэш):
Если zswpin близок к zswpout, значит, кэш работает отлично, и данные редко вытесняются на диск.
Также полезно сравнить zswpin с общим pswpin (чтение с диска):
# Чтение с реального диска
grep pswpin /proc/vmstat
Если pswpin (чтение с диска) сильно меньше, чем zswpin (чтение из zswap), значит, zswap отрабатывает на 100%.
4. Анализ причин отклонения страниц (Rejections)
Иногда ядро отказывается класть страницу в zswap и сразу отправляет ее на диск.
Чтобы понять почему, смотрим счетчики отказов в debugfs:
cat /sys/kernel/debug/zswap/reject_alloc_fail # Не удалось выделить память для сжатой страницы
cat /sys/kernel/debug/zswap/reject_compress_poor # Сжатие неэффективно (страница не сжимается, нет смысла тратить CPU)
cat /sys/kernel/debug/zswap/reject_reclaim_fail # Не удалось освободить место в пуле
Если reject_compress_poor очень большой, возможно, стоит сменить алгоритм сжатия (например, на zstd или lz4) через параметр zswap.compressor.
5. Продвинутая отладка через ftrace (debugfs)
Если вам нужно понять, что именно и когда вытесняется на диск в реальном времени, используйте встроенный трассировщик ядра ftrace через debugfs.
Включаем трассировку событий zswap:
# Включаем трассировку событий zswap
echo 1 > /sys/kernel/debug/tracing/events/zswap/enable
# Очищаем старый лог
echo > /sys/kernel/debug/tracing/trace
# Ждем пару секунд, пока система под нагрузкой поработает со swap...
sleep 5
# Отключаем трассировку
echo 0 > /sys/kernel/debug/tracing/events/zswap/enable
# Смотрим лог
cat /sys/kernel/debug/tracing/trace
Что вы увидите в логе:
zswap_store: Попытка сохранить страницу в кэш.zswap_load: Успешное чтение страницы из кэша (тот самый Hit).zswap_writeback_entry: Самое важное! Событие сброса страницы на диск. Если вы видите много этих событий, значит, пул переполнен.
Готовый скрипт для быстрого сбора метрик (Dashboard)
Чтобы не вводить команды вручную, вот готовый bash-скрипт, который выводит всю сводку в удобном виде.
Сохраните его как zswap_monitor.sh и запускайте от root:
#!/bin/bash
echo "========================================="
echo " ZSWAP MONITORING DASHBOARD "
echo "========================================="
# 1. Текущее состояние
STORED=$(cat /sys/kernel/debug/zswap/stored_pages 2>/dev/null || echo 0)
POOL_SIZE=$(cat /sys/kernel/debug/zswap/pool_total_size 2>/dev/null || echo 0)
WRITTEN_BACK=$(cat /sys/kernel/debug/zswap/written_back_pages 2>/dev/null || echo 0)
STORED_MB=$((STORED * 4096 / 1024 / 1024))
POOL_MB=$((POOL_SIZE / 1024 / 1024))
echo "[1] ТЕКУЩЕЕ СОСТОЯНИЕ КЭША"
echo "Страниц в кэше: $STORED (~${STORED_MB} MB несжатых данных)"
echo "Физически занято: ${POOL_MB} MB"
if [ "$POOL_SIZE" -gt 0 ]; then
RATIO=$(echo "scale=2; ($STORED * 4096) / $POOL_SIZE" | bc)
echo "Коэффициент сжатия: ${RATIO}x"
else
echo "Коэффициент сжатия: N/A (кэш пуст)"
fi
echo ""
echo "[2] ВЫТЕСНЕНИЕ НА ДИСК (Write-backs)"
echo "Страниц сброшено на диск: $WRITTEN_BACK"
if [ "$WRITTEN_BACK" -gt 0 ]; then
echo "ВНИМАНИЕ: Происходит сброс на диск. Возможно, стоит увеличить zswap.max_pool_percent."
fi
echo ""
echo "[3] ПОПАДАНИЯ В КЭШ (Hits / Reads)"
ZSWPIN=$(grep zswpin /proc/vmstat | awk '{print $2}')
ZSWPOUT=$(grep zswpout /proc/vmstat | awk '{print $2}')
PSWPIN=$(grep pswpin /proc/vmstat | awk '{print $2}')
echo "Записано в zswap (zswpout): $ZSWPOUT страниц"
echo "Прочитано из zswap (zswpin / Hits): $ZSWPIN страниц"
echo "Прочитано с диска (pswpin): $PSWPIN страниц"
if [ "$ZSWPOUT" -gt 0 ]; then
HIT_RATE=$(echo "scale=2; ($ZSWPIN * 100) / $ZSWPOUT" | bc)
echo "Hit Rate (попаданий в кэш): ${HIT_RATE}%"
fi
echo ""
echo "[4] ПРИЧИНЫ ОТКАЗОВ (Rejections)"
echo "Ошибка аллокации: $(cat /sys/kernel/debug/zswap/reject_alloc_fail 2>/dev/null || echo 0)"
echo "Плохое сжатие: $(cat /sys/kernel/debug/zswap/reject_compress_poor 2>/dev/null || echo 0)"
echo "Ошибка очистки: $(cat /sys/kernel/debug/zswap/reject_reclaim_fail 2>/dev/null || echo 0)"
echo "========================================="
Важно:
- Если
pool_total_sizeупирается в лимит (20% от RAM по умолчанию), аwritten_back_pagesрастет — увеличьте лимит:echo 30 > /sys/module/zswap/parameters/max_pool_percent. - Если
reject_compress_poorбольшой — попробуйте более агрессивный алгоритм:echo zstd > /sys/module/zswap/parameters/compressor. - Если
zswpin(черезvmstat) значительно большеpswpin— ваша система работает идеально,zswapполностью поглощает swap-активность.
Мы делимся этой технической информацией, чтобы помочь вам в решении задач — используйте её с пониманием. Статья носит рекомендательный характер, поэтому, пожалуйста, применяйте описанные методы осмотрительно.