All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Barry Song (Xiaomi)" <baohua@kernel.org>
To: akpm@linux-foundation.org, linux-mm@kvack.org
Cc: axelrasmussen@google.com, david@kernel.org, hannes@cmpxchg.org,
	kasong@tencent.com, linux-kernel@vger.kernel.org, ljs@kernel.org,
	lyugaofei@xiaomi.com, mhocko@kernel.org, qi.zheng@linux.dev,
	shakeel.butt@linux.dev, stevensd@chromium.org,
	weixugc@google.com, yuanchu@google.com, chenridong@xiaomi.com,
	zhangbo56@xiaomi.com, wangzicheng@honor.com, lianux.mm@gmail.com,
	Barry Song <baohua@kernel.org>
Subject: [RFC PATCH v3 5/6] mm: mglru: run aging when pages are severely imbalanced across gens
Date: Fri, 31 Jul 2026 16:38:42 +0800	[thread overview]
Message-ID: <20260731083843.37811-6-baohua@kernel.org> (raw)
In-Reply-To: <20260731083843.37811-1-baohua@kernel.org>

From: lyugaofei <lyugaofei@xiaomi.com>

This partially restores the reclaim behavior introduced in Yu
Zhao's initial MGLRU commit, ac35a4902370 ("mm: multi-gen LRU:
minimal implementation"):
	/*
	 * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1)
	 * of the total number of pages for each generation. A reasonable range
	 * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The
	 * aging cares about the upper bound of hot pages, while the eviction
	 * cares about the lower bound of cold pages.
	 */
	if (young * MIN_NR_GENS > total)
		return true;
	if (old * (MIN_NR_GENS + 2) < total)
		return true;

But with a stricter condition: the younger generations must
contain at least old_ratio times as many folios as the older
generations. The old_ratio is derived from the lruvec size, so
larger lruvecs use a higher old_ratio. This allows aging to
keep folios of the preferred type distributed across the
reclaimable generations.

Also, imbalanced aging is only applied to non-balanced swappiness
values (for example, < 60 or > 140). For balanced swappiness values
near the middle, the swappiness bias is less of a concern, while the
slightly increased aging overhead might be unacceptable.

Signed-off-by: lyugaofei <lyugaofei@xiaomi.com>
Co-developed-by: Barry Song (Xiaomi) <baohua@kernel.org>
Signed-off-by: Barry Song (Xiaomi) <baohua@kernel.org>
---
 mm/vmscan.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 2e7fef6975b6..98fd2fac90ac 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4973,9 +4973,62 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 	return scanned;
 }
 
+static inline bool swappiness_is_balanced(int swappiness)
+{
+	int range = MAX_SWAPPINESS - MIN_SWAPPINESS;
+	int middle = MIN_SWAPPINESS + range / 2;
+
+	return swappiness >= middle - range / 5 &&
+	       swappiness <= middle + range / 5;
+}
+
+static bool lru_gen_imbalanced(struct lruvec *lruvec, int type,
+		unsigned long max_seq, unsigned long min_seq,
+		struct scan_control *sc, int swappiness)
+{
+	struct lru_gen_folio *lrugen = &lruvec->lrugen;
+	unsigned long young = 0, old = 0, seq;
+	unsigned long old_ratio, gb;
+
+	/* Skip swappiness bias for single-type reclaim or balanced swappiness */
+	if (is_single_type_reclaim(swappiness) || swappiness_is_balanced(swappiness))
+		return false;
+
+	/* More than two generations remain to reclaim */
+	if (min_seq + MIN_NR_GENS < max_seq)
+		return false;
+
+	/*
+	 * Run aging if the only remaining reclaimable generation
+	 * has few folios.
+	 */
+	for (seq = min_seq; seq <= max_seq; seq++) {
+		int gen = lru_gen_from_seq(seq);
+		unsigned long size = 0;
+		int zone;
+
+		for (zone = 0; zone < MAX_NR_ZONES; zone++)
+			size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L);
+
+		if (seq + MIN_NR_GENS > max_seq)
+			young += size;
+		else
+			old += size;
+	}
+	/*
+	 * Copied from inactive_is_low(), but uses a higher old_ratio to
+	 * make aging less aggressive.
+	 */
+	gb = (young + old) >> (30 - PAGE_SHIFT);
+	old_ratio = gb ? int_sqrt(10 * gb) : 1;
+	old_ratio *= MAX_NR_GENS;
+	return young > old * old_ratio;
+}
+
 static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq,
 			     struct scan_control *sc, int swappiness)
 {
+	int type = get_type_to_scan(lruvec, swappiness);
 	DEFINE_MIN_SEQ(lruvec);
 
 	/* have to run aging, since eviction is not possible anymore */
@@ -4987,7 +5040,11 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq,
 		return false;
 
 	/* better to run aging even though eviction is still possible */
-	return evictable_min_seq(min_seq, swappiness) + MIN_NR_GENS == max_seq;
+	if (evictable_min_seq(min_seq, swappiness) + MIN_NR_GENS == max_seq)
+		return true;
+
+	/* Run aging if the preferred type is severely imbalanced across gens */
+	return lru_gen_imbalanced(lruvec, type, max_seq, min_seq[type], sc, swappiness);
 }
 
 static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc,
-- 
2.34.1



  parent reply	other threads:[~2026-07-31  8:39 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-31  8:38 [RFC PATCH v3 0/6] mm: mglru: fix swappiness behavior Barry Song (Xiaomi)
2026-07-31  8:38 ` [RFC PATCH v3 1/6] mm: mglru: prevent min_seq[type] from pointing to an empty generation Barry Song (Xiaomi)
2026-07-31  8:38 ` [RFC PATCH v3 2/6] mm: mglru: let scan_folios() scan both reclaimable generations Barry Song (Xiaomi)
2026-07-31  8:38 ` [RFC PATCH v3 3/6] mm/mglru: improve readability of isolate_folios() Barry Song (Xiaomi)
2026-07-31  8:38 ` [RFC PATCH v3 4/6] mm: mglru: improve scan_folios() exhaustion detection Barry Song (Xiaomi)
2026-07-31  8:38 ` Barry Song (Xiaomi) [this message]
2026-07-31  8:38 ` [RFC PATCH v3 6/6] mm: mglru: run aging if the preferred type has no folios in reclaimable gens Barry Song (Xiaomi)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260731083843.37811-6-baohua@kernel.org \
    --to=baohua@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=axelrasmussen@google.com \
    --cc=chenridong@xiaomi.com \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=kasong@tencent.com \
    --cc=lianux.mm@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=lyugaofei@xiaomi.com \
    --cc=mhocko@kernel.org \
    --cc=qi.zheng@linux.dev \
    --cc=shakeel.butt@linux.dev \
    --cc=stevensd@chromium.org \
    --cc=wangzicheng@honor.com \
    --cc=weixugc@google.com \
    --cc=yuanchu@google.com \
    --cc=zhangbo56@xiaomi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.