Подробный гайд по оптимизации малой памяти в embedded-системахz: swap + zram

Настройка zswap + zram для embedded-систем с малой памятью. Оптимизация swap в RAM, тюнинг сжатия, мониторинг. Подробный гайд по увеличению производительности

2026.07.19                  


Подробный гайд по оптимизации малой памяти в embedded-системахz: swap + zramПодробный гайд по оптимизации малой памяти в embedded-системахz: swap + zram Тема, является одной из самых интересных и сложных в области оптимизации embedded-систем, IoT-устройств и специализированных серверов. Когда у нас есть дефицит оперативной памяти (RAM), а энергонезависимая память (eMMC, SD-карта, NAND) либо отсутствует, либо крайне медленна и ограничена по ресурсу перезаписи (TBW), классический swap на диск неприменим.

Связка zswap + zram позволяет создать двухуровневую иерархию подкачки исключительно в быстрой оперативной памяти, максимизируя эффективность использования каждого мегабайта RAM и минимизируя нагрузку на CPU.

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


1. Архитектурная концепция: Почему именно zswap + zram?

Чтобы понять, как это настраивать, нужно понять, как эти компоненты взаимодействуют:

1. zram (Второй уровень / Бэкинг-девайс):

Создает в RAM виртуальный блочный устройство, которое сжимает данные. В нашем случае оно выступает в роли физического раздела подкачки.


2. zswap (Первый уровень / Фронтенд-кэш):

Это легковесный кэш для страниц подкачки. Он перехватывает страницы, которые ядро хочет отправить в swap, сжимает их и кладет в динамический пул памяти (zpool).


3. Синергия:

Когда динамический пул zswap переполняется, он вытесняет (evict) наименее используемые (LRU) страницы на бэкинг-девайс — то есть на zram.


Преимущества перед просто zram:

  • zswap использует более умные алгоритмы вытеснения (LRU) и пулы памяти, распределяемые на каждый CPU (per-CPU pools), что снижает блокировки (lock contention) в многопоточных средах.
  • zswap может отбрасывать страницы, которые сжимаются плохо (не достигают заданного коэффициента), отправляя их напрямую в zram или вообще отказываясь от их кэширования, экономя CPU.

2. Требования к ядру (Kernel Configuration)

Для работы связки в ядре Linux должны быть включены следующие опции:

CONFIG_ZRAM=m (или =y)
CONFIG_ZSWAP=y
CONFIG_ZPOOL=y
CONFIG_ZSMALLOC=y
# Необходимы алгоритмы сжатия (выберите нужные):
CONFIG_CRYPTO_LZ4=y (или =m)
CONFIG_CRYPTO_ZSTD=y (или =m)
CONFIG_CRYPTO_LZO=y (или =m)

Примечание:

В современных ядрах (5.x+) frontswap интегрирован в zswap, поэтому отдельная опция CONFIG_FRONTSWAP может отсутствовать.


3. Пошаговая настройка

В embedded-системах обычно нет systemd в полном объеме, поэтому настройка часто делается через init-скрипты (OpenRC, procd, busybox init) или udev-правила. Ниже приведен универсальный shell-скрипт, который можно адаптировать.


Шаг 1: Настройка zram (Бэкинг-девайс)

Создаем устройство zram, выделяем под него память и активируем как swap.

#!/bin/sh
# Параметры для zram
ZRAM_DEV="/dev/zram0"
# Размер zram. Для embedded обычно ставят 50%-100% от объема физической RAM.
# Пусть у нас 512 МБ RAM, зададим zram на 256 МБ.
ZRAM_SIZE="256M" 
# Алгоритм сжатия для zram. 
# ВАЖНО: см. раздел про "Двойное сжатие" ниже.
ZRAM_ALG="lz4" 

# Загружаем модуль (если не вкомпилирован в ядро)
modprobe zram num_devices=1

# Настраиваем алгоритм и размер
echo $ZRAM_ALG > /sys/block/zram0/comp_algorithm
echo $ZRAM_SIZE > /sys/block/zram0/disksize

# Форматируем и активируем swap с высоким приоритетом
mkswap $ZRAM_DEV
swapon -p 100 $ZRAM_DEV

Шаг 2: Настройка zswap (Фронтенд-кэш)

Теперь включаем zswap и указываем ему параметры. zswap автоматически подхватит активный swap-девайс (zram0) в качестве бэкинга.

# Включаем zswap
echo 1 > /sys/module/zswap/parameters/enabled

# Алгоритм сжатия для zswap (должен быть быстрым)
echo lz4 > /sys/module/zswap/parameters/compressor

# Используемый пул памяти (zsmalloc оптимален для сжатых страниц)
echo zsmalloc > /sys/module/zswap/parameters/zpool

# Максимальный размер пула zswap в % от общей RAM.
# Для малой памяти ставим 20-30%, чтобы оставить место для приложений.
echo 20 > /sys/module/zswap/parameters/max_pool_percent

4. Глубокий тюнинг (Sysctl и Embedded-специфика)

Для устройств с малой памятью стандартные настройки ядра не подходят.

Добавьте следующие параметры в /etc/sysctl.conf или примените их через sysctl -w:

# 1. Swappiness
# В классической системе 60. В embedded с zswap+zram можно оставить 60 
# или даже увеличить до 80-100, так как swap теперь "быстрый" (в RAM).
# Но если CPU очень слабый, лучше снизить до 10-20, чтобы избежать лишнего сжатия.
vm.swappiness = 60

# 2. Page Cluster
# Определяет, сколько страниц читать за раз при swap-in (2^page-cluster).
# На SD-картах ставили 0. В RAM (zram) последовательное чтение не дает выигрыша, 
# а случайное чтение из сжатой памяти быстрее. Ставим 0 или 1.
vm.page-cluster = 0

# 3. Водяные знаки (Watermarks)
# В embedded часто не хватает highmem. Увеличиваем min_free_kbytes, 
# чтобы ядро раньше начинало освобождать память, не доводя до прямого reclaim.
vm.min_free_kbytes = 8192 # (8 МБ, корректировать под объем RAM)

# 4. OOM Killer
# В embedded лучше убить один процесс, чем получить kernel panic.
vm.oom_kill_allocating_task = 1

5. Критический нюанс: Проблема "Двойного сжатия"

Когда zswap вытесняет страницу в zram, эта страница уже сжата. Если zram настроен на сжатие, он попытается сжать уже сжатые данные.

Это приводит к двум проблемам:

  1. Лишняя трата CPU (процессор пытается сжать энтропийные данные).
  2. Увеличение фрагментации памяти внутри zram.

Решения:

1. Использовать один алгоритм:

Установить в zswap и zram один и тот же алгоритм (например, lz4). Ядро zram достаточно умно, чтобы распознать, что данные уже сжаты алгоритмом lz4, и просто скопировать их (или сжать с коэффициентом 1:1, потратив минимум CPU).

2. Отключить сжатие в zram (если ядро позволяет):

В некоторых кастомных ядрах для embedded можно передать данные в zram без сжатия, но в стандартном mainline zram всегда сжимает. Поэтому рекомендация: используйте lz4 или lzo в обоих компонентах. Не используйте zstd в zram при наличии zswap, так как zstd очень прожорлив до CPU при декомпрессии.


6. Мониторинг и отладка

В embedded-системах важно понимать, что происходит с памятью, чтобы избежать OOM.


Статистика zswap:

cat /sys/kernel/debug/zswap/*

Обратите внимание на:

  • stored_pages — сколько страниц сейчас в кэше zswap.
  • pool_total_size — реальный объем RAM, занятый пулом zswap (в байтах).
  • reject_alloc_fail — если это значение растет, значит, пул zswap переполнен, и ядро не может выделить память даже для метаданных. Уменьшите max_pool_percent или увеличьте RAM.
  • reject_compress_poor — страницы, которые плохо сжимаются и были отправлены напрямую в zram. Если значение огромное, смените алгоритм сжатия.

Статистика zram:

zramctl
# или
cat /sys/block/zram0/mm_stat

Смотрите на orig_data_size и compr_data_size. Коэффициент сжатия должен быть адекватным (обычно 2x - 3x для текстовых/бинарных данных).


Общая статистика swap:

cat /proc/vmstat | grep -E "pswp|zswap"

7. Рекомендации по выбору алгоритмов сжатия

Для embedded-систем выбор алгоритма — это баланс между CPU и RAM:

Алгоритм Скорость CPU Коэффициент сжатия Рекомендация для embedded
lzo / lzo-rle Очень высокая Средний (1.5x - 2x) Идеально для очень слабых CPU (ARM Cortex-A5/A7, MIPS). Минимальная задержка.
lz4 Высокая Средний/Хороший (2x) Золотой стандарт. Отличный баланс. Рекомендуется для zswap и zram.
zstd Средняя/Низкая Отличный (2.5x - 3x+) Использовать только если CPU достаточно мощный (Cortex-A53 и выше), а RAM критически не хватает.

8. важно

  1. [ ] Убедиться, что в ядре есть zswap, zram и нужные крипто-модули.
  2. [ ] Создать zram, задать размер (50-100% от RAM) и алгоритм (например, lz4).
  3. [ ] Активировать zram как swap с высоким приоритетом.
  4. [ ] Включить zswap, задать алгоритм (lz4), пул (zsmalloc) и лимит памяти (20-30%).
  5. [ ] Настроить sysctl (vm.page-cluster=0, адекватный swappiness).
  6. [ ] Провести стресс-тест (например, stress-ng --vm 4 --vm-bytes 80% --vm-method all) и проверить dmesg на наличие OOM и /sys/kernel/debug/zswap/ на наличие ошибок аллокации.

Мы делимся этой технической информацией, чтобы помочь вам в решении задач — используйте её с пониманием. Статья носит рекомендательный характер, поэтому, пожалуйста, применяйте описанные методы осмотрительно.


Статью подготовил: Денис Аверко @Nymexis г. Омск

Комментарии

Загрузка...
Если комментарии не загружаются, можете попробовать отключить блокировщик рекламы для этого сайта