* [PATCH] mm/memory_hotplug: Cache auto_movable stats to optimize online check @ 2025-12-06 21:25 Swaraj Gaikwad 2025-12-07 10:16 ` kernel test robot 2025-12-07 13:30 ` David Hildenbrand (Red Hat) 0 siblings, 2 replies; 4+ messages in thread From: Swaraj Gaikwad @ 2025-12-06 21:25 UTC (permalink / raw) To: David Hildenbrand, Oscar Salvador, Andrew Morton, open list:MEMORY HOT(UN)PLUG, open list Cc: skhan, david.hunter.linux, Swaraj Gaikwad The auto_movable_can_online_movable() function currently walks all populated zones when nid == NUMA_NO_NODE, Since adjust_present_page_count() is called every time memory is onlined/offlined and already updates present page counts, we can maintain cached global statistics that are updated incrementally. This eliminates the need to walk all zones for the NUMA_NO_NODE case. This patch introduces a static global_auto_movable_stats structure that caches kernel_early_pages and movable_pages counts. The cache is updated in adjust_present_page_count() whenever pages are onlined/offlined, and is read directly in auto_movable_can_online_movable() when nid == NUMA_NO_NODE. Testing: Built and booted the kernel successfully. Ran the memory management test suite in tools/testing/selftests/mm/ with ./run_vmtests.sh - all tests passed. Signed-off-by: Swaraj Gaikwad <swarajgaikwad1925@gmail.com> --- mm/memory_hotplug.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 63b9d500ec6c..ba43edba8c92 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -50,6 +50,8 @@ enum { static int memmap_mode __read_mostly = MEMMAP_ON_MEMORY_DISABLE; +static struct auto_movable_stats global_auto_movable_stats; + static inline unsigned long memory_block_memmap_size(void) { return PHYS_PFN(memory_block_size_bytes()) * sizeof(struct page); @@ -851,9 +853,7 @@ static bool auto_movable_can_online_movable(int nid, struct memory_group *group, /* Walk all relevant zones and collect MOVABLE vs. KERNEL stats. */ if (nid == NUMA_NO_NODE) { - /* TODO: cache values */ - for_each_populated_zone(zone) - auto_movable_stats_account_zone(&stats, zone); + stats = global_auto_movable_stats; } else { for (i = 0; i < MAX_NR_ZONES; i++) { pg_data_t *pgdat = NODE_DATA(nid); @@ -1071,12 +1071,13 @@ void adjust_present_page_count(struct page *page, struct memory_group *group, { struct zone *zone = page_zone(page); const bool movable = zone_idx(zone) == ZONE_MOVABLE; + const bool early = early_section(__pfn_to_section(page_to_pfn(page))); /* * We only support onlining/offlining/adding/removing of complete * memory blocks; therefore, either all is either early or hotplugged. */ - if (early_section(__pfn_to_section(page_to_pfn(page)))) + if (early) zone->present_early_pages += nr_pages; zone->present_pages += nr_pages; zone->zone_pgdat->node_present_pages += nr_pages; @@ -1085,6 +1086,12 @@ void adjust_present_page_count(struct page *page, struct memory_group *group, group->present_movable_pages += nr_pages; else if (group && !movable) group->present_kernel_pages += nr_pages; + + if (movable) { + global_auto_movable_stats.movable_pages += nr_pages; + } else if (early) { + global_auto_movable_stats.kernel_early_pages += nr_pages; + } } int mhp_init_memmap_on_memory(unsigned long pfn, unsigned long nr_pages, base-commit: 3cfeff1d2304237b1c14628d695a6df44daff48f -- 2.52.0 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/memory_hotplug: Cache auto_movable stats to optimize online check 2025-12-06 21:25 [PATCH] mm/memory_hotplug: Cache auto_movable stats to optimize online check Swaraj Gaikwad @ 2025-12-07 10:16 ` kernel test robot 2025-12-07 13:30 ` David Hildenbrand (Red Hat) 1 sibling, 0 replies; 4+ messages in thread From: kernel test robot @ 2025-12-07 10:16 UTC (permalink / raw) To: Swaraj Gaikwad, David Hildenbrand, Oscar Salvador, Andrew Morton, linux-kernel Cc: llvm, oe-kbuild-all, Linux Memory Management List, skhan, david.hunter.linux, Swaraj Gaikwad Hi Swaraj, kernel test robot noticed the following build warnings: [auto build test WARNING on 3cfeff1d2304237b1c14628d695a6df44daff48f] url: https://github.com/intel-lab-lkp/linux/commits/Swaraj-Gaikwad/mm-memory_hotplug-Cache-auto_movable-stats-to-optimize-online-check/20251206-235737 base: 3cfeff1d2304237b1c14628d695a6df44daff48f patch link: https://lore.kernel.org/r/20251206212507.135503-1-swarajgaikwad1925%40gmail.com patch subject: [PATCH] mm/memory_hotplug: Cache auto_movable stats to optimize online check config: x86_64-kexec (https://download.01.org/0day-ci/archive/20251207/202512071758.SKaL9BlQ-lkp@intel.com/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251207/202512071758.SKaL9BlQ-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202512071758.SKaL9BlQ-lkp@intel.com/ All warnings (new ones prefixed by >>): >> mm/memory_hotplug.c:53:34: warning: tentative definition of variable with internal linkage has incomplete non-array type 'struct auto_movable_stats' [-Wtentative-definition-incomplete-type] 53 | static struct auto_movable_stats global_auto_movable_stats; | ^ mm/memory_hotplug.c:53:15: note: forward declaration of 'struct auto_movable_stats' 53 | static struct auto_movable_stats global_auto_movable_stats; | ^ 1 warning generated. vim +53 mm/memory_hotplug.c 52 > 53 static struct auto_movable_stats global_auto_movable_stats; 54 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/memory_hotplug: Cache auto_movable stats to optimize online check 2025-12-06 21:25 [PATCH] mm/memory_hotplug: Cache auto_movable stats to optimize online check Swaraj Gaikwad 2025-12-07 10:16 ` kernel test robot @ 2025-12-07 13:30 ` David Hildenbrand (Red Hat) 2025-12-07 23:10 ` Swaraj Gaikwad 1 sibling, 1 reply; 4+ messages in thread From: David Hildenbrand (Red Hat) @ 2025-12-07 13:30 UTC (permalink / raw) To: Swaraj Gaikwad, Oscar Salvador, Andrew Morton, open list:MEMORY HOT(UN)PLUG, open list Cc: skhan, david.hunter.linux On 12/6/25 22:25, Swaraj Gaikwad wrote: > The auto_movable_can_online_movable() function currently walks all > populated zones when nid == NUMA_NO_NODE, > > Since adjust_present_page_count() is called every time memory is > onlined/offlined and already updates present page counts, we can > maintain cached global statistics that are updated incrementally. This > eliminates the need to walk all zones for the NUMA_NO_NODE case. > > This patch introduces a static global_auto_movable_stats structure that > caches kernel_early_pages and movable_pages counts. The cache is updated > in adjust_present_page_count() whenever pages are onlined/offlined, and > is read directly in auto_movable_can_online_movable() when > nid == NUMA_NO_NODE. > > Testing: Built and booted the kernel successfully. Ran the memory > management test suite in tools/testing/selftests/mm/ with > ./run_vmtests.sh - all tests passed. > > Signed-off-by: Swaraj Gaikwad <swarajgaikwad1925@gmail.com> > --- > mm/memory_hotplug.c | 15 +++++++++++---- > 1 file changed, 11 insertions(+), 4 deletions(-) > > diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c > index 63b9d500ec6c..ba43edba8c92 100644 > --- a/mm/memory_hotplug.c > +++ b/mm/memory_hotplug.c > @@ -50,6 +50,8 @@ enum { > > static int memmap_mode __read_mostly = MEMMAP_ON_MEMORY_DISABLE; > > +static struct auto_movable_stats global_auto_movable_stats; > + > static inline unsigned long memory_block_memmap_size(void) > { > return PHYS_PFN(memory_block_size_bytes()) * sizeof(struct page); > @@ -851,9 +853,7 @@ static bool auto_movable_can_online_movable(int nid, struct memory_group *group, > > /* Walk all relevant zones and collect MOVABLE vs. KERNEL stats. */ > if (nid == NUMA_NO_NODE) { > - /* TODO: cache values */ The TODO was a bit unspecific: should have been "cache values if walking all zones becomes a performance problem". Is there a performance impact, or are you able to show a performance difference? -- Cheers David ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/memory_hotplug: Cache auto_movable stats to optimize online check 2025-12-07 13:30 ` David Hildenbrand (Red Hat) @ 2025-12-07 23:10 ` Swaraj Gaikwad 0 siblings, 0 replies; 4+ messages in thread From: Swaraj Gaikwad @ 2025-12-07 23:10 UTC (permalink / raw) To: david Cc: akpm, david.hunter.linux, linux-kernel, linux-mm, osalvador, skhan, swarajgaikwad1925 Hi David, Thank you for the feedback. I've conducted benchmarking to measure the performance impact of caching the global statistics. Test Setup: I created a QEMU VM with the following configuration to simulate a multi-NUMA environment: - 8 NUMA nodes, 1GB each - movablecore=2G kernel parameter - Additional hotpluggable memory region via memmap=1G!0xC00000000 Benchmark Method: I added a debugfs interface to directly invoke auto_movable_can_online_movable() with NUMA_NO_NODE (the code path that walks all zones), and then triggered it via: `echo 1 > /sys/kernel/debug/movable_benchmark` Results: Without patch (walks all zones): 2402 ns With patch (uses cached values): 453 ns While the absolute time difference is small in this test setup, the improvement becomes more significant with: - More NUMA nodes/zones in the system - Frequent memory hotplug operations - Systems with many populated zones If this performance improvement is not considered significant enough to justify the patch, I'm happy to send an updated patch that simply clarifies the TODO comment to: "cache values if walking all zones becomes a performance problem" as you suggested, for future reference. Testing code: static int benchmark_set(void *data, u64 val) { ktime_t start, end; s64 duration; bool result; int nid = NUMA_NO_NODE; unsigned long nr_pages = 32768; start = ktime_get(); result = auto_movable_can_online_movable(nid, NULL, nr_pages); end = ktime_get(); duration = ktime_to_ns(ktime_sub(end, start)); pr_info("BENCHMARK_RESULT: Result=%d | Time=%lld ns\n", result, duration); return 0; } QEMU Configuration: qemu-system-x86_64 \ -m 8G,slots=16,maxmem=16G \ -smp 2 \ -netdev user,id=net0,hostfwd=tcp::10022-:22 \ -device virtio-net-pci,netdev=net0 \ -enable-kvm \ -cpu host \ -initrd "${DEFAULT_INITRD}" \ -kernel "${DEFAULT_KERNEL}" \ -object memory-backend-ram,id=mem0,size=1G \ -object memory-backend-ram,id=mem1,size=1G \ -object memory-backend-ram,id=mem2,size=1G \ -object memory-backend-ram,id=mem3,size=1G \ -object memory-backend-ram,id=mem4,size=1G \ -object memory-backend-ram,id=mem5,size=1G \ -object memory-backend-ram,id=mem6,size=1G \ -object memory-backend-ram,id=mem7,size=1G \ -numa node,nodeid=0,memdev=mem0 \ -numa node,nodeid=1,memdev=mem1 \ -numa node,nodeid=2,memdev=mem2 \ -numa node,nodeid=3,memdev=mem3 \ -numa node,nodeid=4,memdev=mem4 \ -numa node,nodeid=5,memdev=mem5 \ -numa node,nodeid=6,memdev=mem6 \ -numa node,nodeid=7,memdev=mem7 \ -append "loglevel=8 root=/dev/vda3 rootwait console=ttyS0 idle=poll movablecore=2G memmap=1G!0xC00000000" \ -drive if=none,file="${DEFAULT_DISK}",format=qcow2,id=hd \ -device virtio-blk-pci,drive=hd \ -nographic \ -machine q35\ -snapshot \ -s Thanks, Swaraj ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-12-07 17:41 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-12-06 21:25 [PATCH] mm/memory_hotplug: Cache auto_movable stats to optimize online check Swaraj Gaikwad 2025-12-07 10:16 ` kernel test robot 2025-12-07 13:30 ` David Hildenbrand (Red Hat) 2025-12-07 23:10 ` Swaraj Gaikwad
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox