ZRAM/ZSWAP

Материал из ALT Linux Wiki

ZSWAP

Примечание: Для работы этой технологии необходим подмонтированный своп-раздел — без него zswap не работает. Сжатые страницы перед помещением в своп хранит в памяти.

Включить её можно, конечно, параметром ядра, но вовсе не обязательно — достаточно отправить правильную букву в нужный файл:

# echo Y >/sys/module/zswap/parameters/enabled

Юнит запуска/перезапуска/остановки:

/lib/systemd/system/zswap.service  
[Unit]
Description = Enable and configure zswap
DefaultDependencies = no
After = multi-user.target

[Service]
ExecStart = /usr/bin/zswap on
ExecStop = /usr/bin/zswap off
RemainAfterExit = yes

[Install]
WantedBy = swap.target

Посмотреть текущие настройки и статистику можно скриптом, разместив его по доступному для рута пути, соответствующему значению в юните:

/usr/bin/zswap  
#!/bin/sh

LANG=en_US.UTF-8
MODUL=/sys/module/zswap
DEBUG=/sys/kernel/debug/zswap
SWTCH=$MODUL/parameters/enabled
SWAPS=`swapon | grep -cv zram`
ZRAMS=`swapon | grep -c  zram`

Protect(){
    echo "$1"
    exit 1
}

Show(){
    printf "========\n$1\n========\n"
    grep -R . $2 2>&1 | sed '/uevent/d;/\/enabled/d;s|_percent|, %|;s|.*/||;s|:|: |;s|_| |g'
}

case $1 in # switch zswap on/off
    1|Y|y|on)   [ $ZRAMS -gt 0 ] && Protect "can't start: zram-swap is already in use"
                [ $SWAPS -lt 2 ] && Protect "swap partition not found"
                echo Y >$SWTCH;;
    0|N|n|off)  echo N >$SWTCH
esac

case `cat $SWTCH` in # is zswap in use?
    N)  echo zswap disabled ;;
    Y)  Show Settings   $MODUL
        Show Stats      $DEBUG
        PAGE=`cat $DEBUG/stored_pages`
        POOL=`cat $DEBUG/pool_total_size`
        [ $POOL -gt 0 ] &&
            printf "compression ratio: %s\n" `echo "scale=2;4096*$PAGE/$POOL" | bc` ||
            printf "\nzswap is not in use\n"
esac
Пример вывода скрипта  
# zswap
========
Settings
========
same filled pages enabled: Y
enabled: Y
max pool, %: 20
compressor: zstd
zpool: zbud
accept threshold, %: 90
========
Stats
========
same filled pages: 1247
stored pages: 14351
pool total size: 26836992
duplicate entry: 0
written back pages: 0
reject compress poor: 0
reject kmemcache fail: 0
reject alloc fail: 0
reject reclaim fail: 0
pool limit hit: 0
compression ratio: 2.19
Примечание: скрипт позволяет включать/выключать zswap, если тому не препятствует запущенный zram-swap или отсутствие задействованного своп-раздела.

ZRAM

Примечание: Для этой технологии своп-раздел не обязателен, но если таковой наличествует, то по заполнению сжатого свопа в памяти всё остальное начнёт свопиться уже на накопитель.

В дистрибутиве уже есть пакет по фамилии alterator-zram-swap для работы этого типа оптимизации памяти, но он:

  • несколько выморочно высчитывает желаемый размер сжатого свопа;
  • не учитывает уже, возможно, задействованной и несовместимой с ним технологии zswap (см. п. выше);
  • обременён двумя отдельными скриптами запуска и останова службы, когда достаточно одного на всё про всё.

Пакет, в общем-то, и не нужен: достаточно всего пары файлов — юнита и скрипта к нему. Ниже приведён мой вариант обоих, не из пакета.

Юнит:

/lib/systemd/system/zram-swap.service  
[Unit]
Description = Enable and configure zram-swap module
DefaultDependencies = no
After = multi-user.target

[Service]
ExecStop   = /usr/bin/zram-swap stop
ExecStart  = /usr/bin/zram-swap start
ExecReload = /usr/bin/zram-swap restart
RemainAfterExit = yes

[Install]
WantedBy = swap.target

Скрипт:

/usr/bin/zram-swap  
#!/bin/sh

COEFF=512   # Использовать половину ОЗУ  (за счёт сжатия получится меньше четверти).
#COEFF=1024 # Использовать ОЗУ полностью (за счёт сжатия получится меньше половины).
COMPRESS=lz4

PART=zram0
DEV=/dev/$PART
SYSDIR=/sys/block/$PART
ALGO=$SYSDIR/comp_algorithm
ZSWAP=`cat /sys/module/zswap/parameters/enabled`

start(){
    [ "$ZSWAP" == "Y" ] && echo "can't start: zswap is already in use" || {
        modprobe -q zram
        grep -q $COMPRESS $ALGO && echo $COMPRESS >$ALGO
        awk '/MemTotal/{printf "%.0f\n",$2*'$COEFF'}' /proc/meminfo >$SYSDIR/disksize
        mkswap $DEV -L $PART &>/dev/null
        swapon -p 100 $DEV
    }
}

stop(){
    ZRAM=`awk '/zram/{print $1}' /proc/swaps`
    [ -z "$ZRAM" ] || {
        for PART in $ZRAM; do
            swapoff "$PART"
        done && rmmod zram
    }
}

restart(){
    stop
    start
}

status(){
    swapon
}

case $1 in
    start|stop|restart|status) $1;;
    *) restart
esac
Примечание: Переменные из шапки скрипта про долю отжираемой под своп оперативки COEFF и алгоритм сжатия COMPRESS можно вынести в отдельный конфиг /etc/sysconfig/zram-swap и рулить ими оттуда.

Обратная связь