All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] skip empty PUD subtrees during aging with a PUD-level Bloom filter
@ 2026-09-01  6:37 Baoquan He
  2026-09-01  6:37 ` [PATCH v2 1/4] mm/mglru: add MM_WALK_EMPTY stats and tracepoint Baoquan He
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Baoquan He @ 2026-09-01  6:37 UTC (permalink / raw)
  To: linux-mm
  Cc: akpm, baohua, kasong, shakeel.butt, axelrasmussen, yuanchu,
	weixugc, david, rostedt, mhiramat, hannes, Baoquan He

Problem
=======
 
MGLRU's aging walks every present PUD of every mm in the mm_list. When
an mm has no pages on a given NUMA node, all 512 PMDs in each PUD fail
the existing PMD-level Bloom filter test, yet the walker still walks
into every PUD and iterates every PMD. This is pure waste.
 
These cross-node empty walks are structural: lru_gen_use_mm() sets
mm->lru_gen.bitmap to -1 (all nodes) at each context switch, so the
aging walker on every node including kswap, direct reclaim or proactive
aging independently walks the same mm. On the test of 2-node KVM
guest, node 1's walks of the node-0-pinned workload scan ~1235 PTE
entries per walk while finding no folio for node 1's lruvec.

Approach
========
  
Add a PUD-level Bloom filter, one level above the existing PMD filter.
The walker now:
  
  1. Tests the PUD filter before descending into a PUD subtree.
  2. If the PUD had no young entries last generation, skips the entire
     1GB region -- avoiding 512 PMD lookups. 
  3. walk_pmd_range() reports whether it found any young leaf entries;
     walk_pud_range() records that in the double-buffered PUD filter.
  4. The rmap feedback path (lru_gen_look_around()) marks hot PUDs, so
     newly hot or migrated-in regions are re-examined promptly.
  5. force_scan walks bypass the PUD test, so manual aging and newly
     added mm's always re-populate the filter.
 
The double-buffered filter flips each aging generation and the eviction
feedback keeps hot regions marked, so correctness holds without tracking
per-page residency or touching the page fault / rmap hot paths.

Test
====
 
Empty-walk suppression (8GB / 2-NUMA KVM guest, 32 x 64MB workers pinned
to node 0 via numactl --membind=0, 100 aging passes, 3 runs):
 
  node 1 (foreign mm walks):
    baseline (no PUD filter):   ~1235-1254 PTE entries scanned per walk
    with PUD filter:              0.04 / 1.3 / 2.0 per walk
                                (>99.8% reduction; what remains is a few
                                 other processes' pages on node 1,the
                                 cross-node workload mms are fully suppressed)
    pud_skipped:                 ~3.1 1GB subtrees per walk
    worker RSS delta:             0% (no premature reclaim)
 
Build-time regression (make -j4 in a 3G memory cgroup, 4 vCPU / 8GB
2-NUMA KVM guest, 3 runs each; the host was kept idle during the runs):
 
              baseline   patched
  build time  11m48      11m26     (within run-to-run variance; one
                                    patched run of 10m37 was an outlier)
  pgpgin      138k       139k      (unchanged)
  pgmajfault  1950       1950      (unchanged)

The PUD-level filter reduces the leaf scanning of empty aging walks on
the foreign node by >99.8% with no premature reclaim. The build test
shows no measurable regression.

Change log:
==========

v1->v2:
 
- Drop the empty_map (mm-level skip) mechanism. Per Barry Song's
  review, the PUD-level filter alone achieves the goal; empty_map added
  complexity (an mm_struct field, a skip_empty knob, re-scan bookkeeping)
  without being necessary. It can be revisited if very large memory
  systems make the residual walk count meaningful again.
- Rename the counters: MM_LEAF_ELIGIBLE -> MM_LEAF_ASSOCIATED,
  MM_LEAF_TOTAL_EMPTY -> MM_LEAF_EMPTY_WALKS; MM_WALK_EMPTY kept with its
  comment clarified.
- Patch 1 adds the per-walk counters and the mm_vmscan_lru_gen_walk()
  tracepoint used for the measurements below; the series is now 4 patches.

RFC-v1:

- Bloom filter helpers are named symmetrically -
  test/update/reset_pmd_bloom_filter() alongside the PUD-level ones, and
  the struct field filters -> pmd_filters (Barry).
- An mm is marked empty only when its page tables were actually walked
  (a failed mmap_read_trylock() or a stale seq is not empty), and the skip
  is invalidated on the major page-fault and migration paths. (Sashiko)
- Reworked the re-scan: the old shared counter across nodes got stuck at
  the slowest node, so the skip never really engaged. Now each node re-scans
  its empty mms every N passes on its own clock. N is the skip_empty knob
  (default 4, proper read/write with input validation). (Sashiko)
- Added measurement counters/tracepoint, and a kernel-build regression
  test (no measurable impact).

Baoquan He (4):
  mm/mglru: add MM_WALK_EMPTY stats and tracepoint
  mm/mglru: add PUD-level Bloom filter state and generic helpers
  mm/mglru: skip cold PUD subtrees during aging
  mm/mglru: count PUD subtrees skipped by the PUD-level filter

 include/linux/mmzone.h        |  11 ++-
 include/trace/events/vmscan.h |  30 ++++++++
 mm/vmscan.c                   | 132 +++++++++++++++++++++++++++-------
 3 files changed, 147 insertions(+), 26 deletions(-)


base-commit: 42d64d4fef83a241c919c8693fdf0a21b2cb6061
-- 
2.54.0



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-09-04  4:38 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01  6:37 [PATCH v2 0/4] skip empty PUD subtrees during aging with a PUD-level Bloom filter Baoquan He
2026-09-01  6:37 ` [PATCH v2 1/4] mm/mglru: add MM_WALK_EMPTY stats and tracepoint Baoquan He
2026-09-01  7:11   ` Barry Song
2026-09-01  8:18     ` Baoquan He
2026-09-01 23:37       ` Barry Song
2026-09-01  6:37 ` [PATCH v2 2/4] mm/mglru: add PUD-level Bloom filter state and generic helpers Baoquan He
2026-09-01  6:37 ` [PATCH v2 3/4] mm/mglru: skip cold PUD subtrees during aging Baoquan He
2026-09-01 23:53   ` Barry Song
2026-09-02  2:29     ` Baoquan He
2026-09-02  3:22     ` Baoquan He
2026-09-04  3:41       ` Barry Song
2026-09-04  4:38         ` Baoquan He
2026-09-01  6:37 ` [PATCH v2 4/4] mm/mglru: count PUD subtrees skipped by the PUD-level filter Baoquan He

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.