I'm surprised that Linux's handling of large amounts of writes is the way it is
Except it isn't, because it is tunable, and you're just seeing the effects of the default setting.
It is a complex problem if you consider all the different possible workloads a Linux kernel can be used for, from embedded appliances to HPC clusters, and absolutely everything in between.
For a very simple test, run
sudo sh -c 'sync ; echo 3 > /proc/sys/vm/drop_caches ; sync'to flush all currently cached data to disk, and clear all caches. (This is safe, and will never discard data; the only way it can lose data is if you have an actual storage media write error.)
Then, change the duration in which data starts to be considered for writeback. It is in centiseconds (hundredths of a second), and defaults to five seconds (500). Change it to say one second:
sudo sh -c 'echo 100 > /proc/sys/vm/dirty_expire_centisecs'or equivalently
sudo sysctl vm.dirty_expire_centisecs=100There are two main triggers for writeback: online/normal, and background. They are triggered by the amount of cached data, set either in bytes, or as (integer) percentage of memory available for userspace processes. Typical desktop settings on x86-64 are 20% normal limit, and 10% background limit.
Set for example a 1 megabyte background limit,
sudo sh -c 'echo $[1024*1024] > /proc/sys/vm/dirty_background_bytes'and a 32 megabyte online/normal limit,
sudo sh -c 'echo $[32*1024*1024] > /proc/sys/vm/dirty_bytes'or equivalently
sudo sysctl vm.dirty_background_bytes=1048576 vm.dirty_bytes=33554432If the workload is such that it keeps modifying the same file, and we use lazytime to reduce the amount of actual storage writes, we may wish to control how old the data can be before it is actually written back to storage. This is in seconds, and defaults to 12 hours. In your case, consider something like 15 minutes:
sudo sh -c 'echo $[15*60] > /proc/sys/vm/dirtytime_expire_seconds'or equivalently
sudo sysctl vm.dirtytime_expire_seconds=900
To reset all these back to defaults, first run
for N in /proc/sys/vm/dirty* ; do echo "$N: $(cat $N)" ; done to see what the defaults are on your system, then write the ones that default to zeros first, and finally the nonzero values, just like above. They're run-time tunables, usually set at boot time to values set in
/etc/sysctl.conf and/or
/etc/sysctl.d/*.conf unless kernel defaults are used; Linux Mint 20.3 on x86-64 definitely uses kernel defaults.
If you find a set of values you like, all you need to do is create a file, say
/etc/sysctl.d/20-nominal-animal-prefs.conf, containing say
# These are the settings corresponding to the example values Nominal Animal mentioned. vm.dirty_expire_centisecs = 100 vm.dirty_background_bytes = 1048576 vm.dirty_bytes = 33554432 vm.dirtytime_expire_seconds = 900and they will be set at next boot automagically.
For testing, you can create a file that contains the defaults, and one or more files with values you test (perhaps commenting them with your testing results or observations), and load one –– noting that only the specified values are changed; nothing is "reset" to a default –– using
sudo sysctl --load filenameCopying one to
/etc/sysctl.d/ will then use those settings on subsequent boots.
See? I know most users would prefer Linux to just have better defaults, but thing is,
what would be better?
The actual task is to first find the values that work well for you, without causing any annoyances. The suggestions above are just extreme values I pulled out of my backside, good for perhaps starting with, and perhaps not even those, because I haven't experimented with with exactly the kind of workload you're dealing with. I do often lower the dirty limits, because my memory use is "spiky", and if the dirty writeback is too slow, I may have to wait for a second or so for the kernel to evict dirty data before it can provide backing for my multi-gigabyte memory maps.
Yet, when you have found some settings that work for you better –– the tunables are explained in detail at
Linux admin guide, sysctl section –– it is very easy to make them stick.