Re: [PATCH v8 10/16] mm/mglru: Run aging when pages are rare outside the youngest gen
From: Kairui Song
Date: Sat Nov 14 2026 - 12:58:00 EST
On Sat, Nov 14, 2026 at 2:56 AM Barry Song (Xiaomi) <baohua@xxxxxxxxxx> wrote:
>
> From: Gaofei Lyu <lyugaofei@xxxxxxxxxx>
>
> Run aging when the total number of pages outside the youngest
Huge thanks for this!
I really like the imbalance detection idea, as skewed distributions
are very common in real workloads, and this significantly improves
accuracy.
A few trivial nits though:
>
> +static bool lru_gen_imbalanced(struct lruvec *lruvec, struct scan_control *sc,
> + int swappiness)
> +{
> + unsigned long youngest[ANON_AND_FILE] = {0}, old[ANON_AND_FILE] = {0};
> + struct lru_gen_folio *lrugen = &lruvec->lrugen;
> + DEFINE_MAX_SEQ(lruvec);
> + DEFINE_MIN_SEQ(lruvec);
> + int type;
> +
> + if (sc->priority > DEF_PRIORITY / 2)
> + return false;
We have been using "DEF_PRIORITY / 2" so many times in this series
maybe we can introduce a macro like "AGING_PRIORITY" for this later?
And is this condition too hard to trigger?
> +
> + for_each_evictable_type(type, swappiness) {
> + unsigned long seq;
> +
> + youngest[type] = lruvec_gen_size(lrugen, type, max_seq);
> + for (seq = min_seq[type]; seq < max_seq; seq++)
> + old[type] += lruvec_gen_size(lrugen, type, seq);
> + }
> +
> + /* the vast majority of pages sit in the youngest gen */
> + if (youngest[LRU_GEN_ANON] + youngest[LRU_GEN_FILE] >
> + (old[LRU_GEN_ANON] + old[LRU_GEN_FILE]) * MAX_NR_GENS)
> + return true;
We may increase MAX_NR_GENS aggressively in the future (e.g. 64 is
what I have in mind), will MIN_NR_GENS work here? Like what we had
before 798c0330c2ca.
Also counting only the youngest will cause it to drop to 0 very
frequently, as each aging starts with an empty youngest generation.
Perhaps we should look at the yougest MIN_NR_GENS gens (still just
like what we had in 798c0330c2ca).
> +
> + /* Swappiness extremes: the corresponding type matters */
> + if (swappiness == MIN_SWAPPINESS + 1)
> + return youngest[LRU_GEN_FILE] > old[LRU_GEN_FILE] * MAX_NR_GENS;
> +
> + if (swappiness == MAX_SWAPPINESS)
> + return youngest[LRU_GEN_ANON] > old[LRU_GEN_ANON] * MAX_NR_GENS;
Maybe we can do a "round up / down" for swappiness so the two explicit
check can be unified, by reading the right type in the for loop above
directly?
Like doing this before the for_each_evictable_type:
/* Round up or down corner swappiness, to balance the heavy biased
type better */
if (swappiness == MIN_SWAPPINESS + 1)
swappiness = MIN_SWAPPINESS;
else if (swappiness == MAX_SWAPPINESS)
swappiness = MAX_SWAPPINESS + 1;
> +
> + return false;
> +}
And BTW I tested this with FG on top of this using zipf and the result
is even better than before:
IOPS (zipf 1.1, 40G workingset, 16G memcg, mmap access, 3 test runs
for each setup):
mainline: 2,215,641 IOPS
mainline with FG: 2,705,460 IOPS
after this series: 2,182,625 IOPS
after this series with FG: 2,772,968 IOPS
One thing I observed before is that when testing FG, if the generation
number is low, the accuracy drops by a lot since we are trying to
distribute the folios among gens by the frequenecy, so we have a
compressed frequency space. This patch addresses that well so the
performance gain should be larger now.