Raspberry Pi Performance: Add ZRAM and these Kernel Parameters

A couple of weeks ago, I published a Pinebook Pro review article on this blog. Similar to the Pinebook Pro, the Raspberry Pi and more recently the Raspberry Pi 4, are also ARM based. I’ve applied some of the optimizations mentioned in that previous article to the Raspberry Pi 4, with good results. I wanted to share these tweaks and hopefully find out if you also experience the same improvements to performance.

After adding a Raspberry Pi to my Homelab, at times when memory was low, it became very unresponsive and would even freeze. To help address this, I added ZRAM and made a few changes to kernel parameters.

 

Enable ZRAM on the Raspberry Pi

Raspberry Pi zram kernel tweaks

ZRAM creates RAM based block storage named /dev/zram0 (or 1, 2, 3, etc). Pages written there are compressed and stored in-memory. This allows for very fast I/O and also the compression savings provides additional memory.

The Raspberry Pi 4 comes with max memory of 1GB, 2GB or 4GB of RAM. I will be using the 1GB model. This requires some adjustments depending on your use case. With 1GB of ZRAM the default /swapfile (slow!) will now be the last resort. I ended up using this zram-swap script to install and auto configure.

The instructions are listed on that page. Here’s how to install:

git clone https://github.com/foundObjects/zram-swap.git
cd zram-swap && sudo ./install.sh

Optional, if you would like to edit config:

vi /etc/default/zram-swap

Alternatively, you can enable ZRAM by installing zram-tools. If you use this method be sure to edit config located in /etc/default/zramswap and setup around 1GB of ZRAM:

sudo apt install zram-tools

Once installed, you can see the stats of ZRAM’s storage using the following command:

sudo cat /proc/swaps
Filename				Type		Size	Used	Priority
/var/swap                               file		102396	0	-2
/dev/zram0                              partition	1185368	265472	5
pi@raspberrypi:~ $

 

Add Kernel Parameters to make better use of ZRAM

Now, rather than leaving swapping till the last minute, where it often brings the Raspberry Pi to a crippling halt. I’ve added the following lines to /etc/sysctl.conf and rebooted.

These lines will 1) delay the inevitable, running out of memory. This is done by way of increasing the kernel’s cache pressure and 2) start preparing for being out of memory sooner by increasing the tendency of your Raspberry Pi to swap. However, swap will now be stored via much faster ZRAM!

Here are the lines you’ll want to add at the end of your /etc/sysctl.conf file:

vm.vfs_cache_pressure=500
vm.swappiness=100
vm.dirty_background_ratio=1
vm.dirty_ratio=50

Then reboot, or enable with:

sudo sysctl --system

vm.vfs_cache_pressure=500 – increases cache pressure, which increases the tendency of the kernel to reclaim memory used for caching of directory and inode objects. You will use less memory over a longer period of time. The performance hit is negated by the downside of swapping sooner.

vm.swappiness=100 – Increasing how aggressively the kernel will swap memory pages since we are using ZRAM first.

vm.dirty_background_ratio=1 & vm.dirty_ratio=50 – background processes will start writing right away when it hits the 1% limit but the system won’t force synchronous I/O until it gets to 50% dirty_ratio.

These four lines (when used with ZRAM) will help, if like me you know that you will eventually end up using more than the installed memory = swapping. Thus, knowing that you will swap and that ZRAM makes swapping less expensive and can store the data compressed 3 times smaller and begin this swap exchange sooner rather than later.

The cache pressure helps because we are in effect telling the kernel… “hey, look man, I don’t have any extra memory lying around to use for cache so please get rid of it asap and only store the most frequently used/important data”.

Even with reduced caching, if over time we use most of installed memory, the kernel will start opportunistic swapping to ZRAM much sooner so that CPU (compression) and swap I/O aren’t delayed until too late/all at once. ZRAM uses some CPU for compression but in most low-memory scenarios this is much less of a performance hit than swapping without ZRAM enabled.

 

In conclusion

Lets look again at the results:

pi@raspberrypi:~ $ free -h
total used free shared buff/cache available
Mem: 926Mi 471Mi 68Mi 168Mi 385Mi 232Mi
Swap: 1.2Gi 258Mi 999Mi

pi@raspberrypi:~ $ sudo cat /proc/swaps 
Filename Type Size Used Priority
/var/swap file 102396 0 -2
/dev/zram0 partition 1185368 264448 5

264448 in ZRAM is almost 1G of data, compressed. Everything swapped to ZRAM and nothing hit the much slower the /swapfile. Give this setup a try, this will work on all Raspberry Pi models. My setup went from unusable and freezing to performant and stable.

In the near future, I hope to follow up and update this article with some before vs. after results. I just don’t have the time currently to do this. In the meantime, feel free to perform your own tests and let me know in the comments. The Raspberry Pi 4 is a beast with these tweaks. Enjoy!

Related reading:
Linux Performance: Why You Should Almost Always Add Swap Space (2017)
Linux Performance: Almost Always Add Swap. Part 2: ZRAM (2020)

 

Tags: , ,