Re: [PATCH mm-unstable v4 0/2] mm/vmscan: fix NR_ISOLATED accounting and throttling for MGLRU
"Hui Zhu" <[email protected]>
| Newsgroups | org.kernel.vger.linux-kernel,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
> > On Thu, Aug 20, 2026 at 10:49 AM Hui Zhu <[email protected]> wrote: > > > > > From: Hui Zhu <[email protected]> > > > Hello, thanks for the update! > > > > > The legacy reclaim path updates the NR_ISOLATED_ANON/FILE node > > counters around isolation and throttles direct reclaimers via > > too_many_isolated() when isolated folios pile up. The MGLRU eviction > > path does neither: evict_folios() isolates folios without touching > > the counters and never consults too_many_isolated(). > > > > Patch 1 updates NR_ISOLATED_ANON/FILE around isolation in > > evict_folios(), reusing the existing nr_isolated. Without this the > > counters stay at zero while MGLRU reclaim is active, so compaction's > > too_many_isolated() cannot see the pages MGLRU has isolated. > > > > Patch 2 adds throttle_evictable_types() and calls it from > > evict_folios(), before the lruvec lock is taken since throttling > > sleeps, leaving the legacy path untouched. The MGLRU check differs > > from the legacy per-list one in shrink_inactive_list() because > > isolate_folios() picks the type to scan from the refault feedback > > and may fall back to the other one: it computes the set of evictable > > types that are not over-isolated and only sleeps when all of them > > are, waiting once for concurrent reclaimers exactly like the legacy > > path. The mask of the remaining types is passed to isolate_folios(), > > which restricts both its initial choice and its fallback to it, so > > isolation never lands on an over-isolated type and a type that is > > merely over-isolated never blocks the reclaim of the other one. > > This way the MGLRU eviction path backs off when isolated folios pile > > up instead of thrashing the shrinking LRU lists - the scenario the > > too_many_isolated() check exists for. A dying task fakes reclaim > > progress exactly like the legacy path so it exits reclaim quickly. > > > Hmm, could too_many_isolated gets over aggressive or over passive, > since the inactive number of MGLRU is just a compatiblity shim and > does not have the same meaning of classical LRU? Especially when you > run out of swap space or hit a memcg's swap limit, the anon inactive > number becomes a jumpy random number. Proactive aging also makes the > inactive number become huge for MGLRU. I still think even a "/ > MIN_NR_GENS" is better than using inactive value, MGLRU used to use > that as the aging trigger like this: > > if (young * MIN_NR_GENS > total) > return true; > if (old * (MIN_NR_GENS + 2) < total) > return true; > Agreed. The next version drops the inactive-based threshold and instead compares the isolated count against the total evictable pages of the type divided by MIN_NR_GENS, and makes the check per lruvec, where the MGLRU isolation happens. > > > > Testing > > ======= > > > > Test on 8G RAM qemu. > > The reproducer confines stress-ng workers in a 192M memcg and swaps > > through dm-delay (300ms write latency) so pageout is slow and isolated > > folios pile up; the workload is intentionally extreme. nr_isolated_* > > is sampled every 50ms against the per-type too_many_isolated > > threshold (inactive/8), and throttle events are counted via the > > mm_vmscan_throttled tracepoint. > > The test scripts and test log are in [1]. > > > > Test 1, reclaim throttling, parallel direct reclaim in the memcg: > > > > before after > > throttle events (ISOLATED) 0 0 > > - from kswapd 0 0 > > nr_isolated_anon peak 0 3166 > > nr_isolated_file peak 0 174 > > - samples above the > > too_many_isolated threshold 0/1088 89/1077 > > pgscan_direct 1540044096 858332151 > > pswpout 6299497 725819 > > > The throttling avoids premature OOM and over scan when there are too > many reclaimers, it is not for IO balancing. Because writeback folios > are not isolated, they are putback to LRU waiting to be rotated, not > isolated. So reclaimers never wait on the device however slow the > device is (except cgroup V1 have some special quirks I think we should > ignore), it's mostly CPU bound. I think the mechanism might be a bit > outdated, even for classical LRU. > > The result just shows that swap became less aggressive when under > pressure, which is somewhat counter-intuitive. Overly aggressive > throttling will unnecessarily slows performance if anon pages are > actually cold or should be evicted. These results reflect a reclaim > behavior change, not a performance improvement. And I think we > shouldn't rely on throttling for balancing, those are two different > things. Heat or I/O cost-based methods are better. Right. This script is only meant to show that the isolation accounting and the throttling kick in; it was not intended as a performance evaluation. As you pointed out, it also sampled the old node-level inactive-based threshold, which no longer matches the new check. Will provide a new test aimed at the premature OOM / overscanning scenario. > > For example the test you posted, it just stress-ng which only spawns > anon memory IIUC, so when you reclaim file, your code segments got > reclaimed and hence the process stall and has to wait for code > segments IO, which I think it will only slowdown the actual > performance? > Yes, will fix that in the new test as well. Best, Hui