Whenever I ran out of RAM on a Linux system, I used to enable swap memory using the storage device to provide an extra bit of memory. The main advantage is that it’s does not require extra hardware, but come at the cost of much slower access, and potential issues or wear and tear, unless you only use it temporary.
This week-end, I compiled Arm Compute Library on ODROID-XU4Q board, and the first time it crashed because the system ran out of memory, so I enable swap on the eMMC flash module to restart and complete the build successfully. However, I was told it would have been better to enable ZRAM instead.
So what is ZRAM? Wikipedia explains:
zram, formerly called compcache, is a Linux kernel module for creating a compressed block device in RAM, i.e. a RAM disk, but with on-the-fly “disk” compression.
So it’s similar to swap, expect it operates in RAM and compresses memory. It’s also possible to combine it with swap, but if you have to go that route, it may be worth considering upgrading the memory, or changing to a more powerful hardware platform. ZRAM support has been considered stable since Linux 3.14 released in early 2014.
Before showing how to use ZRAM, let’s check the memory in my board.
1 2 3 4 |
free -m total used free shared buff/cache available Mem: 1994 275 1216 30 503 1632 Swap: 0 0 0 |
That’s about 2GB RAM, and swap is disabled. In theory, enabling ZRAM in Ubuntu or Debian should be one simple step:
1 |
sudo apt install zram-config |
Installation went just fine, but it did not enable ZRAM. The first thing to check is whether ZRAM is enabled in the Linux kernel by checking out /proc/config or /proc/config.gz:
1 2 3 |
zcat /proc/config.gz | grep ZRAM CONFIG_ZRAM=m CONFIG_ZRAM_WRITEBACK=y |
ZRAM is built as a module. I tried different things to enable it and check, but I was not sure where to go at this stage at it was almost time to go to bed. What’s usually the best course of action in this case? Stay awake and work overnight to fix the issue? Nope! Rookie mistake. Years of experience have taught me, you just turn off your equipment, and have a good night sleep.
Morning time, breakfast, walk to office, turn on computer and board, et voilà:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
odroid@odroid:~$ free -m total used free shared buff/cache available Mem: 1994 281 1222 22 490 1634 Swap: 997 0 997 odroid@odroid:~$ cat /proc/swaps Filename Type Size Used Priority /dev/zram0 partition 127648 0 5 /dev/zram1 partition 127648 0 5 /dev/zram2 partition 127648 0 5 /dev/zram3 partition 127648 0 5 /dev/zram4 partition 127648 0 5 /dev/zram5 partition 127648 0 5 /dev/zram6 partition 127648 0 5 /dev/zram7 partition 127648 0 5 |
Success! So I would just have had to reboot the board to make it work the previous day… So we have 1GB ZRAM swap enabled across 8 block devices. I assume those are used as needed to avoid eating RAM necessary.
So let’s try to use that swap by making it a bit more challenging that just building the Arm Compute Library, by running a few programs like Chromium and Thunderbird, and monitoring RAM usage at the same time with htop.
At the final stage we can see 506 MB “swap” is used, with 1.11GB memory, probably since the rest of the RAM is used for ZRAM. I was however wrong in myinitial assumption that ZRAM block devices would be used one by one as needed, as all eight devices were show to hold about the same amount of data:
1 2 3 4 5 6 7 8 9 10 |
cat /proc/swaps Filename Type Size Used Priority /dev/zram0 partition 127648 48156 5 /dev/zram1 partition 127648 48452 5 /dev/zram2 partition 127648 47688 5 /dev/zram3 partition 127648 46884 5 /dev/zram4 partition 127648 47780 5 /dev/zram5 partition 127648 47320 5 /dev/zram6 partition 127648 48212 5 /dev/zram7 partition 127648 46948 5 |
That’s the output of free for reference:
1 2 3 4 |
free -m total used free shared buff/cache available Mem: 1994 877 813 47 303 1104 Swap: 997 368 628 |
The good news is that the build could complete just fine with ZRAM, even with Chromium and Firefox running in the background.
ZRAM requires compressing and decompressing data constantly, and reduces the amount of uncompressed RAM your system can access, so it may actually decrease system performance. However, if you run out of RAM frequently or for a specific application it may be worth enabling it. I just needed ZRAM for a single build, so I could disable it now by removing it:
1 |
sudo apt remove zram-config |
However, you may also consider tweaking it by using zramctl utility:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
zramctl --help Usage: zramctl [options] <device> zramctl -r <device> [...] zramctl [options] -f | <device> -s <size> Set up and control zram devices. Options: -a, --algorithm lzo|lz4 compression algorithm to use -b, --bytes print sizes in bytes rather than in human readable format -f, --find find a free device -n, --noheadings don't print headings -o, --output <list> columns to use for status output --raw use raw status output format -r, --reset reset all specified devices -s, --size <size> device size -t, --streams <number> number of compression streams -h, --help display this help -V, --version display version Available output columns: NAME zram device name DISKSIZE limit on the uncompressed amount of data DATA uncompressed size of stored data COMPR compressed size of stored data ALGORITHM the selected compression algorithm STREAMS number of concurrent compress operations ZERO-PAGES empty pages with no allocated memory TOTAL all memory including allocator fragmentation and metadata overhead MEM-LIMIT memory limit used to store compressed data MEM-USED memory zram have been consumed to store compressed data MIGRATED number of objects migrated by compaction MOUNTPOINT where the device is mounted |
Running zramctl without parameters allows use to see which how much actual compressed / uncompressed data is used per block:
1 2 3 4 5 6 7 8 9 10 |
zramctl NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT /dev/zram7 lzo 124.7M 29.8M 9.7M 13M 8 [SWAP] /dev/zram6 lzo 124.7M 30.6M 10.1M 13.5M 8 [SWAP] /dev/zram5 lzo 124.7M 30.5M 9.6M 12.8M 8 [SWAP] /dev/zram4 lzo 124.7M 29.7M 9.9M 10.6M 8 [SWAP] /dev/zram3 lzo 124.7M 29.6M 10.2M 10.9M 8 [SWAP] /dev/zram2 lzo 124.7M 30M 9.6M 10.3M 8 [SWAP] /dev/zram1 lzo 124.7M 30.7M 10.2M 13.4M 8 [SWAP] /dev/zram0 lzo 124.7M 30.4M 9.5M 12.7M 8 [SWAP] |
zramswap service is handled by systemd in Ubuntu 18.04 and you could check out /etc/systemd/system/multi-user.target.wants/zram-config.service to understand how it is setup and control it at boot time too. For example, we can see one block device is set per processor. Exynos 5422 is an eight core processor, and that’s why we have 8 block devices here. Any other tips are appreciated in comments.

Jean-Luc started CNX Software in 2010 as a part-time endeavor, before quitting his job as a software engineering manager, and starting to write daily news, and reviews full time later in 2011.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress