Linux Kernel: The multi-generational LRU
lwn.net
lwn.net
>> On Chrome OS, our real-world benchmark that browses popular websites in multiple tabs demonstrates 51% less CPU usage from kswapd and 52% (full) less PSI on v5.11
In addition, direct reclaim latency is reduced by 22% at 99th percentile and the number of refaults is reduced 7%. These metrics are important to phones and laptops as they are correlated to user experience.
>> Use cases
On Android, our most advanced simulation that generates memory pressure from realistic user behavior shows 18% fewer low-memory kills, which in turn reduces cold starts by 16%.
On Borg, a similar approach enables us to identify jobs that underutilize their memory and downsize them considerably without compromising any of our service level indicators.
On Chrome OS, our field telemetry reports 96% fewer low-memory tab discards and 59% fewer OOM kills from fully utilized devices and no UX regressions from underutilized devices.
https://engineering.fb.com/2014/02/27/web/an-analysis-of-fac...
http://www.cs.cornell.edu/~qhuang/papers/sosp_fbanalysis.pdf
> Quadruply-segmented LRU. Four queues are maintained at levels 0 to 3. On a cache miss, the item is inserted at the head of queue 0. On a cache hit, the item is moved to the head of the next higher queue (items in queue 3 move to the head of queue 3). Each queue is allocated 1/4 of the total cache size and items are evicted from the tail of a queue to the head of the next lower queue to maintain the size invariants. Items evicted from queue 0 are evicted from the cache.
Going off on a tangent here, but I've always felt there should be an easy way to read through files without causing the kernel to cache them into memory. When I grep through the odd multi-GB file I sometimes/often don't want that to be cached. Looking through the flags for open(2) I see O_DIRECT. Wonder if it'd make sense to expose that as an option in grep, or if there's a handy library somebody made that I could preload to anything to get that effect.
I think the solution is not to come up with clever heuristics, but to use a tiny neural net which predicts "how many hours till this page is accessed again?".
Train the net using a tiny sample of reads and writes.
Obviously the net needs to be really tiny to run on every single page read, but I believe even say a network with 50 weights would outperform today's heuristics.
A key thing however was that their actual predictor was a simpler model, SVM, designed using insight discovered from the behavior of the neural network one. In particular the source address was a strong indicator for the model.
I don't argument for excess simplicity, but if you can't explain (critical) behavior of your code without referring to a big matrix of NN weights, it's probably a bad idea.
Thus, this paper has shown how we can use deep learning in an offline setting to derive insights that lead to an improved set of features with which to make predictions for cache replacement. More broadly, our approach in designing Glider suggests that deep learning can play an important role in systematically exploring features and feature representations that can improve the effectiveness of much simpler models, such as perceptrons and SVMs.
The specific predictor they created was integer based, so could be used in a non-floating point kernel:
We then use an SVM with the k-sparse binary feature. Since integer operations are much cheaper in hardware than floating point operations, we use an Integer SVM (ISVM) with an integer margin and learning rate of 1.
Again this highlights the interesting point of the paper, IMHO.
This is why instructions like dcbz exist on POWER - to tell it to not bother reading in the next cache line because you're about to write to it.
Related: The experimental async aware (io_uring optimized) Glommio API may eventually supplant POSIX I/O.
https://github.com/DataDog/glommio
"Modern storage is plenty fast. It is the APIs that are bad." https://itnext.io/modern-storage-is-plenty-fast-it-is-the-ap...
There is however GNU dd which supports direct i/o ('direct' flag) for ages.
One of my biggest use cases for it is with soxi, which I use solely for playlist manipulation. I don't alias my source tree search tools, because invariably I'm going to want all that stuff in the cache anyway for builds and such.
> When I grep through the odd multi-GB file I sometimes/often don't want that to be cached.
What are you hoping to gain here? The only place I could imagine this might be an issue is on a HDD-using (as opposed to SSD) server that serves a lot of files, which you might evict with your grepping, causing a lot of random IO activity later because the server needs to read everything from disk again to serve requests.
But as a "odd" one-off I probably just wouldn't care.
[1] https://github.com/torvalds/linux/blob/ac3a0c8472969a03c0496...
[2] https://github.com/torvalds/linux/blob/1590a2e1c681b0991bd42...
[3] https://docs.google.com/spreadsheets/d/16wEq5QBzqOtownEtZvZe...
[4] https://github.com/ben-manes/caffeine/blob/master/simulator/...
[5] https://github.com/ben-manes/caffeine/blob/master/simulator/...
Its an incredibly difficult problem to try to figure out what to keep in cache, so I find that the first thing one should allow is for the user to give hints.
It would be great if there was a way for applications to designate some memory allocations as "hot" or "cold" to indicate the usage pattern, or indicate that its reading something linearly, or that its about to need something.
https://www.man7.org/linux/man-pages/man2/madvise.2.html
> MADV_RANDOM
> MADV_SEQUENTIAL
> MADV_WILLNEED
> MADV_DONTNEED
> MADV_COLD
> MADV_PAGEOUT
> MADV_DONTDUMP
> MADV_WIPEONFORK
See e.g. https://www.putorius.net/systemd-tmpfiles.html#user-specific... (no affiliation with the site, it was just the first one I found that describes the works).