Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Baoquan He <baoquan.he@linux.dev>
To: Barry Song <baohua@kernel.org>
Cc: Baoquan He <hebaoquan@kylinos.cn>,
	linux-mm@kvack.org, akpm@linux-foundation.org, david@kernel.org,
	rostedt@goodmis.org, mhiramat@kernel.org, kasong@tencent.com,
	qi.zheng@linux.dev, shakeel.butt@linux.dev,
	axelrasmussen@google.com, yuanchu@google.com, weixugc@google.com,
	baolin.wang@linux.alibaba.com, hannes@cmpxchg.org
Subject: Re: [PATCH 2/9] mm/mglru: suppress cross-node empty page table walks
Date: Fri, 28 Aug 2026 15:26:35 +0800	[thread overview]
Message-ID: <apE4K3PnupiUG63g@fedora> (raw)
In-Reply-To: <CAGsJ_4yC+2-Hx8wXop9bXPsAk7ZH=p=ZS1QmfyePKYK-VKhRXA@mail.gmail.com>

On 08/28/26 at 02:35pm, Barry Song wrote:
> On Mon, Aug 24, 2026 at 3:38 PM Baoquan He <hebaoquan@kylinos.cn> wrote:
> >
> > In the current MGLRU, lru_gen_use_mm() will mark one process's mm used
> > on all nodes at each context switch. So each nodes's aging walks into
> > each mm's page tables. For an mm with memory on one or only a subset of
> > nodes, the other nodes' walks find no pages for one lruvec. While these
> > empty walks are pure waste.
> >
> > Track per-mm, per-node empty-walk marks: bit N on mm->lru_gen.empty_map is
> > set when node N's walk of the mm found no page for this lruvec, and
> > get_next_mm() will skip the mm on node N between re-scan passes. The re-scan
> > is driven by each node's own pass count (mm_state->seq), so every
> > mglru_empty_skip_gens-th (default 4) pass re-walks all empty-marked mms to
> > close migration/NUMA-balancing windows; keeping it on the node's own clock
> > avoids a shared "oldest marking" sequence latching at the slowest node.
> >
> > A walk is "empty" when it traversed the page tables and found no folio for
> > this lruvec.
> >
> > A page that appears on the node during the skip (fault or migration) is not
> > aged until the re-scan; a later patch invalidates the skip on those
> > paths. mm_struct grows by 8 bytes per process.
> 
> Hi Baoquan,
> 
> As mentioned in my reply to the cover letter, I wonder if this could
> be achieved by the PUD filter instead.
> 
> For example, if we find no associated folios in a PUD, could we simply
> filter out the entire PUD?
> 
> BTW, is this related to memory policies such as `MPOL_BIND`? If so,
> could we inspect the mempolicy to avoid these empty walks in the first
> place?
> 
> I'm not quite sure what the best solution is. My gut feeling is that
> `empty_map` adds quite a bit of complexity, so I'd like to explore
> whether there are alternative ways to avoid the extra code and the
> additional space in `mm_struct` before going with this approach.
> 
> So far, I'm not really against `empty_map`; I'm just trying to get a
> better understanding of it and explore whether there are simpler
> alternatives.
> 
> I mean, I really like your PUD filter, but I'm not quite as fond of
> the `empty_map` approach. :-)

Thanks a lot for your careful reviewing, Barry, really appreciated.

I totally understand your preference. When I found the defect of
mm->lru_gen.bitmap, I was also very hesitant about the final solution.
empty_map is the specific solution, PUD filter is a generic one
while benefit mm->lru_gen.bitmap too. I agree with you that PUD filter
is good enough to resolve the defect of mm->lru_gen.bitmap, and benefit
even non-NUMA systems. Maybe in future when huge system RAM, e.g several
TeraBytes of memory becomre normal, we can come back to consider adding
the empty_map solution.

That said, I will drop the empty_map related code changes and post v2.

> 
> >
> > Signed-off-by: Baoquan He <hebaoquan@kylinos.cn>
> > ---
> >  include/linux/mm_types.h |  3 +++
> >  include/linux/mmzone.h   |  2 ++
> >  mm/vmscan.c              | 52 ++++++++++++++++++++++++++++++++++------
> >  3 files changed, 50 insertions(+), 7 deletions(-)
> >
> > diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> > index 6d815f6440c9..3738e8877b73 100644
> > --- a/include/linux/mm_types.h
> > +++ b/include/linux/mm_types.h
> > @@ -1410,6 +1410,8 @@ struct mm_struct {
> >                          * page table walkers cleared the corresponding bits.
> >                          */
> >                         unsigned long bitmap;
> > +                       /* bit N: node N's last walk found no folio; skip until re-scan */
> > +                       unsigned long empty_map;
> >  #ifdef CONFIG_MEMCG
> >                         /* points to the memcg of "owner" above */
> >                         struct mem_cgroup *memcg;
> > @@ -1503,6 +1505,7 @@ static inline void lru_gen_init_mm(struct mm_struct *mm)
> >  {
> >         INIT_LIST_HEAD(&mm->lru_gen.list);
> >         mm->lru_gen.bitmap = 0;
> > +       mm->lru_gen.empty_map = 0;
> >  #ifdef CONFIG_MEMCG
> >         mm->lru_gen.memcg = NULL;
> >  #endif
> > diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> > index 229d27fbfb54..30213a880db0 100644
> > --- a/include/linux/mmzone.h
> > +++ b/include/linux/mmzone.h
> > @@ -633,6 +633,8 @@ struct lru_gen_mm_walk {
> >         int batched;
> >         int swappiness;
> >         bool force_scan;
> > +       /* this aging pass is an empty-walk re-scan pass (every K-th) */
> > +       bool rescan_pass;
> >  };
> >
> >  /*
> > diff --git a/mm/vmscan.c b/mm/vmscan.c
> > index 92cb83a78971..e8ba49683b28 100644
> > --- a/mm/vmscan.c
> > +++ b/mm/vmscan.c
> > @@ -2710,6 +2710,14 @@ static bool should_clear_pmd_young(void)
> >         return arch_has_hw_nonleaf_pmd_young() && get_cap(LRU_GEN_NONLEAF_YOUNG);
> >  }
> >
> > +/*
> > + * Cross-node empty walk suppression. lru_gen_use_mm() marks an mm used on all
> > + * nodes, so aging on a node where the mm has no memory wastes a full page table
> > + * walk. Skip such an mm for up to MGLRU_EMPTY_SKIP_GENS generations after an
> > + * empty walk, then force-rescan to close migration/mlock/NUMA-balancing windows.
> > + */
> > +#define MGLRU_EMPTY_SKIP_GENS 4
> 
> Is this related to `MAX_NR_GENS`? Does that mean that, over a full
> aging cycle, we have a `1 / MAX_NR_GENS` chance of doing a rescan?
> 
> Best Regards
> Barry
> 


  reply	other threads:[~2026-08-28  7:26 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-24  7:37 [PATCH 0/9] mm/mglru: suppress empty page table walks during aging Baoquan He
2026-08-24  7:37 ` [PATCH 1/9] mm/mglru: add MM_WALK_EMPTY stats and tracepoint Baoquan He
2026-08-28  5:37   ` Barry Song
2026-08-28  7:46     ` Baoquan He
2026-08-31  8:17       ` Baoquan He
2026-08-24  7:37 ` [PATCH 2/9] mm/mglru: suppress cross-node empty page table walks Baoquan He
2026-08-28  6:35   ` Barry Song
2026-08-28  7:26     ` Baoquan He [this message]
2026-08-24  7:38 ` [PATCH 3/9] mm/mglru: add debugfs knob for the empty-walk skip threshold Baoquan He
2026-08-24  7:38 ` [PATCH 4/9] mm/mglru: invalidate empty-walk skip on page fault and migration Baoquan He
2026-08-24  7:38 ` [PATCH 5/9] mm/mglru: add PUD-level Bloom filter state Baoquan He
2026-08-24  7:38 ` [PATCH 6/9] mm/mglru: refactor Bloom filter helpers for two filter levels Baoquan He
2026-08-24  7:38 ` [PATCH 7/9] mm/mglru: skip PUD subtrees during aging Baoquan He
2026-08-24  7:38 ` [PATCH 8/9] mm/mglru: report hot PUDs from the rmap feedback path Baoquan He
2026-08-24  7:38 ` [PATCH 9/9] mm/mglru: count PUD subtrees skipped by the PUD-level filter Baoquan He
2026-08-24  8:11 ` [PATCH 0/9] mm/mglru: suppress empty page table walks during aging Baoquan He
2026-08-24  8:42 ` Baoquan He
2026-08-28  6:11 ` Barry Song
2026-08-28  7:42   ` Baoquan He

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=apE4K3PnupiUG63g@fedora \
    --to=baoquan.he@linux.dev \
    --cc=akpm@linux-foundation.org \
    --cc=axelrasmussen@google.com \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=hebaoquan@kylinos.cn \
    --cc=kasong@tencent.com \
    --cc=linux-mm@kvack.org \
    --cc=mhiramat@kernel.org \
    --cc=qi.zheng@linux.dev \
    --cc=rostedt@goodmis.org \
    --cc=shakeel.butt@linux.dev \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox