7

Consider the following scenario. You have a slow read-only media (e.g. write-protected Thumb Drive, CD/DVD, whatever) that you installed Linux on (not a Live CD per se, but a normal build), and use it on a computer with literally no other forms of storage. It's slow, because it is USB 2. The root filesystem is mounted as overlayfs so that it's "writeable" for logs and a lot of other temporary work you do, but all writes go to RAM (tmpfs upperdir). Pretty typical scenario for a Live distro situation.

Since there is no other forms of storage, swap is mounted on zram. So when Linux decides to swap, it compresses those pages and stores them still in RAM, but at least they're compressed. This is actually decent, since the RAM of most applications is easily compressible (RAM is usually very redundant in data since it's meant to be "fast"). This works well for application memory, but not for tmpfs.

Here's the thing: zram is fast, incredibly so. The Thumb Drive, on the other hand, is slow. Let's say it's 20 MiB/s, which is really slow in comparison. You can see the problem and why the kernel will not do the right thing here.

Note that this question is not a duplication of How to make files inside TMPFS more likely to swap. The question is pretty much the same, but I'm not satisfied with that answer in that question whatsoever, sorry. The kernel definitely does not do the "right thing" by itself, regardless of how smart the people designing it are. I dislike it when people don't understand the situation and think they know better. They cater to the average case. That's why Linux is so tweakable, because no matter how smart it is, it can't predict what it will be used for.

For example, I can (and did) set vm.swappiness (/proc/sys/vm/swappiness) to 100, which tells it to swap application memory aggressively and keep the file cache. This option is nice, but it's not everything, unfortunately.

I want it to prioritize keeping the file cache over any other RAM use when dealing with swap. That's because dropping the file cache results in it having to read back from the slow 20 MiB/s drive, which is much much slower than swapping to zram. For applications, the vm.swappiness works, but not for tmpfs.

tmpfs is mounted as page cache, so it has the same priority as the file cache. If you read a file from tmpfs, it will prioritize it over an older file cache entry (most recently used). But that's bad, the kernel clearly does not do the right thing here. It should consider that swapping tmpfs to zram is much better even if it's "used more recently" than the file cache because reading from the drive is very slow.

So I need to explicitly tell it to swap from tmpfs more often compared to the file cache: that it should preserve the file cache more than tmpfs. There are so many options in /proc/sys/vm but nothing for this that I could find. Disappointing really.

Failing that, is there a way to tell the kernel that some devices/drives are just that much more slower than others, and it should prefer to keep the cache for them more than others? tmpfs and zram are fast. The thumb drive is not. Can I tell the kernel this information?

It can't do "the right thing" by itself if it treats all drives the same. It's much faster to swap tmpfs to a fast drive like zram than to drop caches from a slow drive, even if tmpfs is used more recently.

When it runs out of free memory it will start to either swap application memory (good) due to swappiness, or drop old file caches (bad). If I end up re-reading from those files, it will be very slow. Much slower than if it decided to swap some tmpfs, even if recently used, and then read from it again. Because zram is an order of magnitude faster.

5
  • 1
    You may want to tone down that attitude. How the kernel works isn't generally the fault of unix.SE users, and the answer in the question you linked to also doesn't represent the opinions of every user reading this one. (Instead, it's just the opinion of one user, seen reasonable by six others.)
    – ilkkachu
    May 17, 2018 at 15:03
  • 1
    Sorry, I only said that because far too many people are eager to mark questions as duplicates, but I did my research before and I don't like the "accepted answer" of that question. I'm not saying that the answerer is wrong, but it definitely does not answer the question, except with the last paragraph, when it's said that you "can't control it". I was hoping there was, though.
    – kktsuri
    May 17, 2018 at 15:17
  • 1
    I might even agree in principle with that answer, but still value this question. This question raises a specific problem, which is interesting to reason about - even if we can't find a solution. The other question doesn't provide a very strong motivation. I think the general answer to the other question is that this is not something to worry about... and that you probably don't want to use very much of tmpfs. If you have reason to doubt either response, then that reason is the key part of your question.
    – sourcejedi
    May 17, 2018 at 15:32
  • @sourcejedi: the link you posted in your answer pretty much confirms that Linux really is lacking in this regard. And I don't mean just the "force tmpfs to swap over the file cache". This is a specific problem of the more general "which devices are faster and should be prioritized for swapping" in fact. You can set priority on swaps, but that only applies between swaps. There's no way to set the "priority" (or lack of) on a file-backed cache. If a drive is slow, its file cache should have a high priority compared to a fast drive (or swap). Not 100% of course, but a high priority nonetheless.
    – kktsuri
    May 17, 2018 at 15:38
  • Gah, I hope that last sentence or two of mine did not cause too much confusion or annoyance. I mean, on a typical desktop install which is using tmpfs for /tmp, you generally wouldn't want to put too much in /tmp, and you generally wouldn't have a reason to worry about swapping it. So I think the specific motivation for asking is quite important. Your question, here, specifies such a motivation. The other one did not, which is why I think it got a more general answer.
    – sourcejedi
    May 17, 2018 at 16:21

1 Answer 1

5

Increasing the swappiness value makes the kernel more willing to swap tmpfs pages, and less willing to evict cached pages from the other filesystems which are not backed by swap.

Since zram swap is faster than your thumb drive, you ideally want to increase swappiness above 100. This is only possible in kernel version 5.8 or above. Linux 5.8 allows swappiness to be set to a maximum of 200.

For in-memory swap, like zram or zswap, [...] values beyond 100 can be considered. For example, if the random IO against the swap device is on average 2x faster than IO from the filesystem, swappiness should be 133 (x + 2x = 200, 2x = 133.33).

-- Documentation/admin-guide/sysctl/vm.rst


Further reading

tmpfs is treated the same as any other swappable memory

See the kernel commit "vmscan: split LRU lists into anon & file sets" -

Split the LRU lists in two, one set for pages that are backed by real file systems ("file") and one for pages that are backed by memory and swap ("anon"). The latter includes tmpfs.

- and the code at linux-4.16/mm/vmscan.c:2108 -

/*
 * Determine how aggressively the anon and file LRU lists should be
 * scanned.  The relative value of each set of LRU lists is determined
 * by looking at the fraction of the pages scanned we did rotate back
 * onto the active list instead of evict.
 *
 * nr[0] = anon inactive pages to scan; nr[1] = anon active pages to scan
 * nr[2] = file inactive pages to scan; nr[3] = file active pages to scan
 */
static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
               struct scan_control *sc, unsigned long *nr,
               unsigned long *lru_pages)
{
    int swappiness = mem_cgroup_swappiness(memcg);

...

    /*
     * With swappiness at 100, anonymous and file have the same priority.
     * This scanning priority is essentially the inverse of IO cost.
     */
    anon_prio = swappiness;
    file_prio = 200 - anon_prio;

Linux 5.8 allows swappiness values up to 200

mm: allow swappiness that prefers reclaiming anon over the file workingset

With the advent of fast random IO devices (SSDs, PMEM) and in-memory swap devices such as zswap, it's possible for swap to be much faster than filesystems, and for swapping to be preferable over thrashing filesystem caches.

Allow setting swappiness - which defines the rough relative IO cost of cache misses between page cache and swap-backed pages - to reflect such situations by making the swap-preferred range configurable.

This was part of a series of patches in Linux 5.8. In previous versions, Linux "mostly goes for page cache and defers swapping until the VM is under significant memory pressure". This is because "the high seek cost of rotational drives under which the algorithm evolved also meant that mistakes could quickly result in lockups from too aggressive swapping (which is predominantly random IO)."

This series sets out to address this. Since commit ("a528910e12ec mm: thrash detection-based file cache sizing") we have exact tracking of refault IO - the ultimate cost of reclaiming the wrong pages. This allows us to use an IO cost based balancing model that is more aggressive about scanning anonymous memory when the cache is thrashing, while being able to avoid unnecessary swap storms.

These patches base the LRU balance on the rate of refaults on each list, times the relative IO cost between swap device and filesystem (swappiness), in order to optimize reclaim for least IO cost incurred.

-- [PATCH 00/14] mm: balance LRU lists based on relative thrashing v2

11
  • That is interesting indeed, but unfortunately tmpfs is still considered "equal" to the file cache, since it's mounted as page cache, no matter the swappiness. +1 for the link though, very interesting read.
    – kktsuri
    May 17, 2018 at 15:20
  • That's what I read all over, not just on stackexchange (but here as well). Also, kernel.org/doc/Documentation/filesystems/tmpfs.txt seems to somewhat confirm it. Plus, my own tests seem to confirm it. For example, in gkrellm, tmpfs storage shows up in "cached" along with all other caches rather than "used" -- the latter is the memory taken up by applications, so clearly it is different. I think tmpfs is "anonymous cache" rather than "file-backed", but it's still cache and not "application memory". And swappiness of 100 doesn't seem to effect it. I'll try more links.
    – kktsuri
    May 17, 2018 at 15:26
  • I would not say that "application memory" is a well-defined term here. If you mmap() a file with MAP_PRIVATE (copy-on-write) and read from a page of that memory, you're accessing the page cache. That page will be shared with all other mappings, and accounted as "cache". However, if you write to such a page... that's when you get copy-on-write behaviour. You get a private copy of the page, which will never written back to the file. If such a private page is to be evicted from main memory, then it must be saved to swap instead. Such a page is accounted as "used".
    – sourcejedi
    May 17, 2018 at 15:43
  • In general, I think tmpfs showing up as "cache" is a bit of a misleading artefact of the implementation. I would be surprised if it misled the swappiness logic in the same way, but I haven't verified yet!
    – sourcejedi
    May 17, 2018 at 15:46
  • 1
    Edited answer to provide evidence for tmpfs pages being treated the same as anonymous pages.
    – sourcejedi
    May 17, 2018 at 16:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .