More memory with ZRAM
Some of my machines have only little memory and I looked for a better way to utilize what little memory there is in the system. Without being able to increase the physical memory available, there are basically 3 options here:
- Disable unused applications
- Reduce the memory footprint of running applications
- Cheat :-)
KSM
KSM (Kernel Samepage Merging) is a memory-saving de-duplication feature but it's only really useful for applications using the madvise(2) system call and is often used when hosting virtual machines, e.g. KVM. I'm not running KVM on this machine but activated it anyway - but no application seems to usemadvise(2) and it didn't help anything regarding memory usage.zswap
There's zswap, a lightweight compressed cache for swap pages. But instead of a real swap device, the compression takes place in a dynamically allocated memory pool. To enable it, the system must be booted withzswap.enabled=1 but I didn't want to reboot my system just yet, so I skipped that option for now.Update: I've enabled
zswap in the same VM from the zram test below and ran the same test - but the results are rather irritating:
$ awk '{print $NF}' /proc/cmdline
zswap.enabled=1
$ i=0; while true; do
[ $i -gt 2000 -a `expr $i % 50` = 0 ] && printf "$i "
bash -c "sleep 10000 &"; i=$((i+1))
done
2050 2100 2150 2200 2250 2300 ^C
$ free -m
total used free shared buff/cache available
Mem: 241 192 3 0 46 7
Swap: 127 127 0
$ pgrep -c sleep
2333
$ grep -r . /sys/kernel/debug/zswap/
/sys/kernel/debug/zswap/stored_pages:24754
/sys/kernel/debug/zswap/pool_total_size:50696192
/sys/kernel/debug/zswap/duplicate_entry:0
/sys/kernel/debug/zswap/written_back_pages:32762
/sys/kernel/debug/zswap/reject_compress_poor:456
/sys/kernel/debug/zswap/reject_kmemcache_fail:0
/sys/kernel/debug/zswap/reject_alloc_fail:0
/sys/kernel/debug/zswap/reject_reclaim_fail:0
/sys/kernel/debug/zswap/pool_limit_hit:16253
We max out at ~2300 instances of bash & sleep which is even less than when running without any compression...?zram
zram has been around for a while now and looked like the most promising contender. On a machine with 1GB RAM, I'd allocate 75% for our compressed swap device:$ modprobe zram $ echo 768M > /sys/block/zram0/disksize $ mkswap /dev/zram0 $ swapon -p2 /dev/zram0The machine is quite busy and it doesn't take long until it starts swapping to our new swap device1):
$ grep . /sys/block/zram0/{num_{reads,writes},{compr,orig}_data_size}
/sys/block/zram0/num_reads:1953540
/sys/block/zram0/num_writes:2333028
/sys/block/zram0/orig_data_size:671141888
/sys/block/zram0/compr_data_size:283552915
The compression ration is quite good, we're using only 42% of our precious real memory. I wanted to do some tests though to see if this can be measured in some kind of micro benchmark. In a 256MB Fedora Linux VM, we started GNU/bash along with /bin/sleep over and over again, let see how far we got:
$ i=0; while true; do
[ $i -gt 2400 -a `expr $i % 50` = 0 ] && printf "$i "
bash -c "sleep 10000 &"; i=$((i+1))
done
2450 2500 2550 2600 2650 2700 ^C
$ pgrep -c sleep
2711
$ free -m
total used free shared buff/cache available
Mem: 241 192 3 0 45 5
Swap: 127 127 0
All memory is used up and starting any more programs is almost impossible now. This was repeatable, it always stopped around ~2700 instances and then came to a grinding halt. Let's try again with ZRAM:
$ pkill sleep
$ modprobe zram && echo 128M > /sys/block/zram0/disksize && mkswap /dev/zram0 && swapon -p2 /dev/zram0
$ i=0; while true; do
[ $i -gt 2500 -a `expr $i % 100` = 0 ] && printf "$i "
bash -c "sleep 10000 &"; i=$((i+1))
done
2600 2700 2800 2900 3000 3100 3200 ^C
$ pgrep -c sleep
3201
$ free -m
total used free shared buff/cache available
Mem: 241 186 2 0 52 6
Swap: 255 209 46
With ZRAM enabled, it maxes out at ~3100, and makes it up to 3200 if we wait a bit longer (although we still seem to have 46MB free swap available). Again, this is also repeatable. And since we're only starting the same program over and over again, our compression ratio is even better1):
$ grep . /sys/block/zram0/{num_{reads,writes},{compr,orig}_data_size}
/sys/block/zram0/num_reads:55002
/sys/block/zram0/num_writes:70129
/sys/block/zram0/orig_data_size:128086016
/sys/block/zram0/compr_data_size:34523998
Btw, did someone say DriveSpace? :-)1) Note: these sysfs entries will be deprecated in future kernel versions,