From: Ridong Chen <ridong.chen@linux.dev>
To: David Hildenbrand <david@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
Johannes Weiner <hannes@cmpxchg.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, Kairui Song <kasong@tencent.com>,
Qi Zheng <qi.zheng@linux.dev>,
Shakeel Butt <shakeel.butt@linux.dev>,
Barry Song <baohua@kernel.org>,
Axel Rasmussen <axelrasmussen@google.com>,
Yuanchu Xie <yuanchu@google.com>, Wei Xu <weixugc@google.com>,
Baoquan He <baoquan.he@linux.dev>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Joanne Koong <joannelkoong@gmail.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
Ridong Chen <ridong.chen@linux.dev>,
Ridong Chen <chenridong@xiaomi.com>
Subject: [RFC PATCH 2/3] mm/mglru: skip the flags cmpxchg when nothing changes
Date: Thu, 5 Nov 2026 21:22:19 +0800 [thread overview]
Message-ID: <20261105132220.2233677-3-ridong.chen@linux.dev> (raw)
In-Reply-To: <20261105132220.2233677-1-ridong.chen@linux.dev>
From: Ridong Chen <chenridong@xiaomi.com>
folio_update_gen() and folio_set_lru_refs() always end with a
try_cmpxchg() on folio->flags, even when the new value equals the old
one. The locked instruction still takes the struct page cacheline in
exclusive state.
That is common in practice: a folio mapped by many processes is visited
once per mm during a page table walk, and after the first visit it is
already in the youngest generation with refs cleared and PG_workingset
set. isolate_folio() and the eviction paths also call
folio_set_lru_refs(folio, 0) on folios whose refs are already zero.
Break out of the loop when the flags would not change. The result is
the same as a successful no-op cmpxchg. The only difference is that the
full barrier implied by the locked instruction is gone on that path.
No caller relies on it: the eviction and isolation callers run under
the LRU lock, and the others (page table walks, folio_mark_accessed(),
lru_gen_clear_refs()) only care about the resulting flags value, which
is already in place. Note that lru_gen_inc_refs() already returns
without any atomic when refs is at LRU_REFS_MAX and the folio is in
the workingset.
Tested on an i7-13700HX with turbo disabled and the performance
governor. N processes map the same 2GiB tmpfs file (huge=never) and
read every page, then one aging pass is triggered on their memcg
through /sys/kernel/debug/lru_gen ("+ <memcg_id> 0 <max_seq> 200 1").
Time per aging pass in ms, median of 5 runs of 10 passes each, averaged
over 2 boots of each kernel:
processes base patched
1 32.9 31.7 -3.5%
8 195.1 160.2 -17.9%
32 755.8 592.2 -21.7%
64 1597.2 1260.6 -21.1%
With one process, every visit changes the generation, so there is
nothing to skip. Before the patch, perf annotate attributes 53-58% of
the walk_update_folio() samples to the lock cmpxchg in the inlined
folio_update_gen() in this test.
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
include/linux/mm_inline.h | 2 ++
mm/vmscan.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index b3d85fe91385..4ba9079f4dc8 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -244,6 +244,8 @@ static inline void folio_set_lru_refs(struct folio *folio, unsigned int refs)
do {
new_flags = old_flags;
lru_set_refs_flags(&new_flags, refs);
+ if (new_flags == old_flags)
+ break;
} while (!try_cmpxchg(folio_flags(folio, 0), &old_flags, new_flags));
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 50c352e9ffef..3fa76715382d 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3398,6 +3398,8 @@ static int folio_update_gen(struct folio *folio, int new_gen, int *type,
lru_set_gen_flags(&new_flags, new_gen);
lru_set_refs_flags(&new_flags, 0);
new_flags |= BIT(PG_workingset);
+ if (new_flags == old_flags)
+ break;
} while (!try_cmpxchg(folio_flags(folio, 0), &old_flags, new_flags));
*type = folio_flags_is_file_lru(&old_flags);
--
2.34.1
next prev parent reply other threads:[~2026-11-05 13:23 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 13:22 [RFC PATCH 0/3] mm/mglru: cacheline follow-ups on the reclaim hot paths Ridong Chen
2026-11-05 13:22 ` [RFC PATCH 1/3] mm/mglru: skip redundant bitmap store in lru_gen_use_mm() Ridong Chen
2026-11-05 13:22 ` Ridong Chen [this message]
2026-11-05 16:21 ` [RFC PATCH 2/3] mm/mglru: skip the flags cmpxchg when nothing changes Kairui Song
2026-11-06 1:43 ` Ridong Chen
2026-11-07 10:39 ` Kairui Song
2026-11-07 12:04 ` Ridong Chen
2026-11-08 8:50 ` Barry Song
2026-11-08 11:49 ` Ridong Chen
2026-11-05 13:22 ` [RFC PATCH 3/3] mm/mglru: move lrugen atomic stats off the read-mostly lines Ridong Chen
2026-11-08 9:14 ` Barry Song
2026-11-08 12:49 ` Ridong Chen
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=20261105132220.2233677-3-ridong.chen@linux.dev \
--to=ridong.chen@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=axelrasmussen@google.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=baoquan.he@linux.dev \
--cc=chenridong@xiaomi.com \
--cc=david@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=joannelkoong@gmail.com \
--cc=kasong@tencent.com \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=qi.zheng@linux.dev \
--cc=rppt@kernel.org \
--cc=shakeel.butt@linux.dev \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=weixugc@google.com \
--cc=yuanchu@google.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.