All of 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: 18+ 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-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 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.