From: "Hui Zhu" <hui.zhu@linux.dev>
To: Johannes Weiner <hannes@cmpxchg.org>,
Michal Hocko <mhocko@kernel.org>,
Roman Gushchin <roman.gushchin@linux.dev>,
Shakeel Butt <shakeel.butt@linux.dev>,
Muchun Song <muchun.song@linux.dev>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
Qi Zheng <qi.zheng@linux.dev>, Lorenzo Stoakes <ljs@kernel.org>,
Kairui Song <kasong@tencent.com>, Barry Song <baohua@kernel.org>,
Axel Rasmussen <axelrasmussen@google.com>,
Yuanchu Xie <yuanchu@google.com>, Wei Xu <weixugc@google.com>,
cgroups@vger.kernel.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org
Cc: Hui Zhu <zhuhui@kylinos.cn>
Subject: [PATCH v2 0/3] mm: workingset: fix the shadow node budget under MGLRU
Date: Mon, 31 Aug 2026 17:46:08 +0800 [thread overview]
Message-ID: <cover.1788169145.git.zhuhui@kylinos.cn> (raw)
From: Hui Zhu <zhuhui@kylinos.cn>
Commit 7404bd37cfbe ("mm: workingset: use lruvec_lru_size() to get the
number of lru pages") broke the workingset shadow node budget under
MGLRU: lruvec_lru_size() reads mz->lru_zone_size, which MGLRU never
maintains, so count_shadow_nodes() sees the evictable LRU lists as
empty and the shadow shrinker reclaims eviction tokens almost as fast
as they are created, losing thrashing protection.
Patch 1 switches count_shadow_nodes() back to lruvec_page_state_local(),
which both classic LRU and MGLRU maintain.
Patch 2 addresses the reparenting race that motivated 7404bd37cfbe:
patch 1 makes cgroup v2 read state_local as well, so extend the
dying-memcg stat redirection (previously cgroup v1 only) to all
hierarchies.
Patch 3 recovers the performance. Patch 2 added an unconditional
rcu_read_lock() to the stat update fast path; patch 3 moves the dying
check out of the RCU read-side critical section so the lock is only
taken on the rare dying path.
Performance testing
===================
The test script and the raw results are available at [1].
Environment: 10-vCPU QEMU guest, 8 GiB RAM, cgroup v2; 7 runs per
configuration, medians reported. Workloads:
w1-anon-churn: single-threaded anon fault/charge loop in a memcg
(MADV_DONTNEED + re-fault, no reclaim). Every touch
is a real fault with charge and memcg stat updates,
so it stresses exactly the fast path patch 2 changes.
w2-file-churn: file read loop under memory.high pressure
(reclaim-bound, noisier).
w3-reparent: reparent accounting sanity check.
w1-anon-churn (pages/s):
classic LRU MGLRU
base 4393028 4377122
patches 1-2 4385996 (-0.2%) 4352887 (-0.6%)
patches 1-3 4381832 (-0.3%) 4377053 (+0.0%)
w2-file-churn (MB/s):
classic LRU MGLRU
base 8277 8226
patches 1-2 8226 (-0.6%) 8123 (-1.3%)
patches 1-3 8157 (-1.4%) 8294 (+0.8%)
w3-reparent passed on all kernels.
Patch 2 alone shows a small overhead, most visible under MGLRU (-0.6%
on w1); patch 3 brings w1 back to the base level in both LRU
configurations. The remaining differences are within run-to-run
noise.
[1] https://gist.github.com/teawater/32f373ec41d185d840455eb167321a5a
Hui Zhu (3):
mm: workingset: use lruvec_page_state_local() to count lru pages
mm: memcg: redirect stats updates of dying memcgs for all hierarchies
mm: memcg: skip the RCU lock when the memcg is not dying
mm/memcontrol.c | 30 ++++++++++++------------------
mm/workingset.c | 5 ++---
2 files changed, 14 insertions(+), 21 deletions(-)
--
2.53.0
next reply other threads:[~2026-08-31 9:46 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 9:46 Hui Zhu [this message]
2026-08-31 9:46 ` [PATCH v2 1/3] mm: workingset: use lruvec_page_state_local() to count lru pages Hui Zhu
2026-09-03 17:51 ` Shakeel Butt
2026-09-03 17:55 ` Shakeel Butt
2026-08-31 9:46 ` [PATCH v2 2/3] mm: memcg: redirect stats updates of dying memcgs for all hierarchies Hui Zhu
2026-09-03 17:52 ` Shakeel Butt
2026-09-03 17:56 ` Shakeel Butt
2026-08-31 9:46 ` [PATCH v2 3/3] mm: memcg: skip the RCU lock when the memcg is not dying Hui Zhu
2026-09-03 17:57 ` Shakeel Butt
2026-09-03 17:53 ` [PATCH v2 0/3] mm: workingset: fix the shadow node budget under MGLRU Shakeel Butt
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=cover.1788169145.git.zhuhui@kylinos.cn \
--to=hui.zhu@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=axelrasmussen@google.com \
--cc=baohua@kernel.org \
--cc=cgroups@vger.kernel.org \
--cc=david@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=kasong@tencent.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@kernel.org \
--cc=muchun.song@linux.dev \
--cc=qi.zheng@linux.dev \
--cc=roman.gushchin@linux.dev \
--cc=shakeel.butt@linux.dev \
--cc=weixugc@google.com \
--cc=yuanchu@google.com \
--cc=zhuhui@kylinos.cn \
/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.