DATE CHECKED THIS PAGE WAS VALID: 14/09/2023
On Linux systems, especially Debian some very old defaults are used. While this made sense 10-15 years ago, they are less optimal today, and changing the defaults is a very slow process since the logic is “if it aint broke don't fix it”. In some ways this is very useful as little changes, so you can expect a consistent experience between versions. However sometimes there is an issue. This is one of those times.
The default for Debian to start running kswapd (which compresses pages of memory and reclaims unused memory) is to wait for the system to have less than 80 Megabytes of memory left.
As you can imagine, many programs in 2023 have heavy memory requirements, even simple apps like web browsers, and many systems have 16GB or more RAM so waiting until only 80MB of memory is left does not seem like an optimal amount. When this is reached, the system must now perform extensive work reclaiming old pages and compacting them, while under memory pressure. This is most likely not an ideal time to do this, and will cause the “freezing” you notice while you wait for this to happen in the background. While doing this, new memory requests are placed in a queue until memory can be freed up, again which is not ideal. Most apps expect memory to be served on demand. All of these factors lead me to conclude setting more sane defaults is a logical step.
So instead of these defaults Debian ships with, we want to change them so that the system spends time earlier, ideally before all the memory is used up, backgrounding this process and avoiding the freezing a user may experience.
The 2 tweakable values we will deal with are:
Both of these are edited in your sysctrl.conf file and placed at the end. To check your current values you would do something like:
Most likely a value of 10 is returned. This means 0.1% of memory. A value of 100 is 1% and a value of 1000 is 10%. Valid values are between 1-1000. The second value of min_free_kbytes default is 67584. This can be any value in KB.
On the left is the default option. On the right an 8GB system that has had the optimizations I suggest is displayed.
The min value is calculated from the min_free_kbytes. That is about 64MB. The scale factor determines the low and high value by multiplying the system RAM by the scale factor and adding it to the min_free_kbytes. In our example that is 8192*0.1% = 8MB. 64MB is thus the minimum value, and 64+8 = 72MB for the low value and +8 again for 80MB which is the high value.
This determines that once the system falls below 72MB kswapd wakes up and starts trying to reclaim memory pages. It stops doing this when it gets back to 80MB. However as the next limit is very close (just 64MB) the possibility exists that the application requesting memory will likely request more than 8MB, meaning it will immediately hit the min limit. When this happens all memory requests are placed in a queue and served only when memory is freed up. This is very irritating for an end user on a desktop system.
So lets set some different values. My testing has resulted in a suggestion of 2.5% of total memory for both the minimum and scale factors. This was done with trial and error so I am sure that more optimal values exist, however they serve as just fine values in my testing and do not cause any problems.
So for an 8GB system, 2.5% is 8192*2.5% which is approximately 204MB or around 204000K. Please do not fixate on exact values, the computer does not care all that much.
So what we want to do is set a minimum of 204000 min_free_kbytes per 8GB and scale factor of 2.5% which is a value of 250. This will result in the example on the right hand side of the diagram. To clarify, if you have some other multiple of RAM you can multiply the min_free_kbytes by the multiple. The scale factor will stay the same. So here are the values:
And so on. This means that Your system will start reclaiming memory when 5% is left and stop when it reaches 7.5% of total RAM. This is more logical to me but you can set other values if you have some disagreement, Im just telling you what worked for me.
To edit this simply:
sudo nano /etc/sysctl.conf
and add to the end of the file:
vm.watermark_scale_factor=250 vm.min_free_kbytes= INSERT YOUR VALUE HERE
After a reboot you can check the values are accepted and you have tweaked the memory performance of the system :)