2019年12月31日 星期二

Zram memory compress in embedded linux 5/6

1. Kconfing
gedit ~/linux-6.6.x/drivers/block/zram/Kconfig
choice
    prompt "Default zram compressor"
    ###default ZRAM_DEF_COMP_LZORLE
    default ZRAM_DEF_COMP_ZSTD
    depends on ZRAM

#config ZRAM_DEF_COMP_LZORLE
#    bool "lzo-rle"
#    depends on CRYPTO_LZO

config ZRAM_DEF_COMP_ZSTD
    bool "zstd"
    depends on CRYPTO_ZSTD

#config ZRAM_DEF_COMP_LZ4
#    bool "lz4"
#    depends on CRYPTO_LZ4

#config ZRAM_DEF_COMP_LZO
#    bool "lzo"
#    depends on CRYPTO_LZO

#config ZRAM_DEF_COMP_LZ4HC
#    bool "lz4hc"
#    depends on CRYPTO_LZ4HC

#config ZRAM_DEF_COMP_842
#    bool "842"
#    depends on CRYPTO_842
endchoice

2. defconfig use zram only no zswap
CONFIG_X86_MSR=y                                    # cpupower need only in x64
CONFIG_SWAP=y                                           # System Switching Memory
CONFIG_ZSWAP=n                                        # Pre-I/O compression
CONFIG_ZPOOL=n                                        # zswap using
CONFIG_ZBUD=n                                          # zswap using
CONFIG_Z3FOLD=n                                      # zswap using
CONFIG_ZRAM=m
CONFIG_ZRAM_DEF_COMP_ZSTD=y
CONFIG_ZRAM_WRITEBACK=y                    #Allow writeback to disk
CONFIG_ZRAM_MEMORY_TRACKING=n  # Track memory usage
CONFIG_ZSMALLOC=y                                # ZRAM Memory Allocator (Important!)
CONFIG_ZSMALLOC_CHAIN_SIZE=8        # Optional: chain size (Linux v6 required)
CONFIG_CRYPTO_ZSTD=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y

3. cpupower tool
###setting CROSS CFLAGS LDFLAGS, cpupower auto find libpci.so
gedit ~/linux-5.10.107/tools/power/cpupower/Makefile
CROSS = $(CROSS_COMPILE)
CC = $(CROSS)gcc
LD = $(CROSS)gcc
AR = $(CROSS)ar
STRIP = $(CROSS)strip
RANLIB = $(CROSS)ranlib
HOSTCC = gcc
MKDIR = mkdir
CFLAGS=$(STAGING_CFLAGS)
LDFLAGS=$(STAGING_LDFLAGS) -lz -ludev -lcap

gedit ~/build/Makefile
###after linux and third party lib installed run kernel-install-cpupower
kernel-install-cpupower:
    @echo "install cpupower..."
    @[ -d $(KERNEL_BUILD_DIR)/tools/power/cpupower ] || install -m 755 -d $(KERNEL_BUILD_DIR)/tools/power/cpupower
    @[ -d $(DESTDIR)/usr/lib ] || install -m 755 -d $(DESTDIR)/usr/lib
    @[ -d $(DESTDIR)/usr/bin ] || install -m 755 -d $(DESTDIR)/usr/bin
    @$(MAKE) -C $(KERNEL_SRC_DIR)/tools/power/cpupower O=$(KERNEL_BUILD_DIR)/tools/power/cpupower
    @$(CMD_CP) -f  $(KERNEL_BUILD_DIR)/tools/power/cpupower/libcpupower.* $(DESTDIR)/usr/lib
    @$(CMD_CP) -f  $(KERNEL_BUILD_DIR)/tools/power/cpupower/cpupower $(DESTDIR)/usr/bin

4. inittab
gedit ~/build/skeleton/etc/inittab
###after /volume1 mount run zraminit.sh
# Initialize the ZRAM equipment(this should be done before the main services start)
::sysinit:/etc/script/zraminit.sh
::once:/etc/script/zramwbwatch.sh

5. zraminit.sh
#!/bin/sh -x
#using [-x] for debugging
echo "ZRAM Starting..."

# Cpu strategy
cpupower frequency-set -g performance

for epp in /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference; do
    if [ -f "$epp" ]; then
        echo "Setting $epp to performance"
        echo "performance" > "$epp"
    fi
done

# Load zram module
modprobe zram num_devices=1

remain=10
while [ ! -b /dev/zram0 ] && [ "$remain" -gt 0 ]; do
    echo "Waiting for /dev/zram0 to be ready... remaining attempts: $remain"
    sleep 0.1
    remain=$((remain - 1))
done

if [ -f /sys/block/zram0/reset ]; then
    echo 1 > /sys/block/zram0/reset
fi

# set the compression algorithm
if [ -f /sys/block/zram0/comp_algorithm ]; then
    echo "zstd" > /sys/block/zram0/comp_algorithm
fi

# Set the compression algorithm
echo "zstd" > /sys/block/zram0/comp_algorithm

if [ -d /sys/block/zram0 ]; then
    if mountpoint -q "/volume1"; then
        #writeback 8GB
        if [ ! -f "/volume1/zram_back" ]; then
            echo "Creating backing file..."
            dd if=/dev/zero of="/volume1/zram_back" bs=1M count=8192
        fi

        #clean up all old loop devices with zram_back
        for old_looping in $(losetup -a | grep "/volume1/zram_back" | cut -d ':' -f 1); do
            echo "Unbinding old loop: $old_looping"
            losetup -d "$old_looping"
        done

        LOOP_DEV=$(losetup -f)
        if [ -n "$LOOP_DEV" ]; then
            echo "Using $LOOP_DEV as backing..."
            if losetup "$LOOP_DEV" "/volume1/zram_back"; then
                if ! echo "$LOOP_DEV" > /sys/block/zram0/backing_dev; then
                    echo "Error: failed to bind $LOOP_DEV to zram0"
                    losetup -d "$LOOP_DEV"
                fi
            else
                echo "Error: could not associate $LOOP_DEV with /volume1/zram_back"
                losetup -d "$LOOP_DEV"
            fi
        else    
            echo "Error: no free loop devices found!"
        fi
    fi

    # Use half physical memory
    memkb=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
    zsize=$((memkb * 1024 / 2))
    echo $zsize > /sys/block/zram0/disksize

    # Format as swap
    mkswap /dev/zram0
    swapon /dev/zram0 -p 100 # Use appropriate priority

    # must set minimum free memory watermark to __setup_per_zone_wmarks
    minwater=$((memkb / 8))
    if [ "$minwater" -gt 262144 ]; then
        minwater=262144
    fi
    sysctl -w vm.min_free_kbytes=$minwater
    # low watermark = min watermark + distance, distance calculate from scale factor
    sysctl -w vm.watermark_scale_factor=100
    # setting 0 to 200 allows the system to more actively utilize compressed space
    sysctl -w vm.swappiness=100
    # read ahead 2^n page, n=0 page=1
    sysctl -w vm.page-cluster=0
fi

6. zramwbwatch.sh
#!/bin/sh -x
#using [-x] for debugging

bdstatus=$(cat /sys/block/zram0/backing_dev)
if [ -n "$bdstatus" ] && [ "$bdstatus" != "none" ]; then
    while true; do

        memused=$(free | awk '$1 == "Mem:" {printf "%d", ($2-$7)/$2*100}')

        if [ "$memused" -gt 80 ]; then
            echo "[$(date)] memory usage ${memused}% > 80%, execute ZRAM writeback..."
            echo all > /sys/block/zram0/idle
            echo huge > /sys/block/zram0/writeback
            echo idle > /sys/block/zram0/writeback
        fi

        sleep 30

    done
fi

7. monitor zram working
watch -n1 "cat /proc/swaps"

###memory usage%
watch -n1 "free | grep Mem | awk '{print int((\$2-\$7)/\$2*100)}'"

watch -n1 "cat /sys/block/zram0/mm_stat"
orig_data_size | compr_data_size | mem_used_max | mem_limit | mem_used_total same_pages | pages_compacted | huge_pages

watch -n1 "cat /sys/block/zram0/bd_stat"
pages_on_bd | bd_reads bd_| writes

###give memory stress
(DATA=$(dd if=/dev/urandom bs=1M count=50); sleep 120; unset DATA) &

refer to:
For writeback feature, user should set up backing device before the zram working.
https://lore.kernel.org/all/1498459987-24562-10-git-send-email-minchan@kernel.org/T/#u

沒有留言:

張貼留言