Re: [linux-next:master] [vmalloc] 60ced5818f: stress-ng.shm.ops_per_sec 7.2% regression

Yeoreum Yun <[email protected]> Mon, 15 Jun 2026 10:51:48 +0100
Newsgroups dev.linux.lists.oe-lkp,org.kvack.linux-mm
Message-ID <ai/[email protected]>
> > 
> > 
> > Hello,
> > 
> > kernel test robot noticed a 7.2% regression of stress-ng.shm.ops_per_sec on:
> > 
> > 
> > commit: 60ced5818f64ac356620d1ad3e0d473c457dbf5b ("vmalloc: optimize vfree with free_pages_bulk()")
> > https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git master
> > 
> > [still regression on linux-next/master 7da7f07112610a520567421dd2ffcb51beaefbcc]
> > 
> > testcase: stress-ng
> > config: x86_64-rhel-9.4
> > compiler: gcc-14
> > test machine: 192 threads 2 sockets Intel(R) Xeon(R) 6740E  CPU @ 2.4GHz (Sierra Forest) with 256G memory
> > parameters:
> > 
> > 	nr_threads: 100%
> > 	testtime: 60s
> > 	test: shm
> > 	cpufreq_governor: performance
> > 
> > 
> > 
> > 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 <[email protected]>
> > | Closes: https://lore.kernel.org/oe-lkp/[email protected]
> > 
> > 
> > Details are as below:
> > -------------------------------------------------------------------------------------------------->
> > 
> > 
> > The kernel config and materials to reproduce are available at:
> > https://download.01.org/0day-ci/archive/20260602/[email protected]
> > 
> > =========================================================================================
> > compiler/cpufreq_governor/kconfig/nr_threads/rootfs/tbox_group/test/testcase/testtime:
> >   gcc-14/performance/x86_64-rhel-9.4/100%/debian-13-x86_64-20250902.cgz/lkp-srf-2sp3/shm/stress-ng/60s
> > 
> > commit: 
> >   4aa4abf1f1 ("mm/page_alloc: optimize free_contig_range()")
> >   60ced5818f ("vmalloc: optimize vfree with free_pages_bulk()")
> > 
> > 4aa4abf1f14bd6d0 60ced5818f64ac356620d1ad3e0 
> > ---------------- --------------------------- 
> >          %stddev     %change         %stddev
> >              \          |                \  
> >    1103082            -7.2%    1024016        stress-ng.shm.ops
> >      18394            -7.2%      17072        stress-ng.shm.ops_per_sec
> >    2084775           -23.1%    1602693 ±  3%  stress-ng.time.involuntary_context_switches
> >  3.076e+08            -7.3%  2.852e+08        stress-ng.time.minor_page_faults
> >      14759           -21.1%      11646        stress-ng.time.percent_of_cpu_this_job_got
> >       8806           -21.1%       6946        stress-ng.time.system_time
> >      86.08            -7.5%      79.66        stress-ng.time.user_time
> >    2799689            -1.3%    2762252        stress-ng.time.voluntary_context_switches
> >  1.125e+09 ±  6%     +42.3%  1.601e+09 ± 13%  cpuidle..time
> >    2089564 ±  3%     +25.6%    2624591 ±  2%  cpuidle..usage
> >     360.33           -22.5%     279.35 ± 44%  turbostat.PkgWatt
> >      36.35           -22.6%      28.12 ± 44%  turbostat.RAMWatt
> >     198.28 ±  2%      +9.2%     216.55        vmstat.procs.r
> >     131962            -6.3%     123686        vmstat.system.cs
> >   14039730 ±  2%     -18.1%   11503879 ± 18%  numa-meminfo.node0.MemUsed
> >     175943 ± 13%    +114.1%     376780 ±  2%  numa-meminfo.node0.PageTables
> >     184811 ± 13%    +105.7%     380127 ±  4%  numa-meminfo.node1.PageTables
> >       9.32 ±  5%      +3.2       12.57 ± 11%  mpstat.cpu.all.idle%
> >       3.69 ±  9%      +5.6        9.29 ±  4%  mpstat.cpu.all.soft%
> >      85.37            -8.6       76.73        mpstat.cpu.all.sys%
> >       1.38            -0.2        1.19 ±  3%  mpstat.cpu.all.usr%
> >  4.555e+08            -7.4%  4.216e+08        numa-numastat.node0.local_node
> >  4.557e+08            -7.5%  4.217e+08        numa-numastat.node0.numa_hit
> >  4.493e+08            -6.8%  4.187e+08        numa-numastat.node1.local_node
> >  4.494e+08            -6.8%  4.189e+08        numa-numastat.node1.numa_hit
> >     193547            +7.4%     207908 ±  3%  perf-stat.i.cpu-clock
> >     193547            +7.4%     207908 ±  3%  perf-stat.i.task-clock
> >     135837            -8.5%     124266 ±  2%  perf-stat.ps.context-switches
> >    5141774           -11.4%    4555341 ±  2%  perf-stat.ps.minor-faults
> >    5141776           -11.4%    4555343 ±  2%  perf-stat.ps.page-faults
> >     194174           +12.8%     219047        meminfo.KReclaimable
> >   24232028            -8.6%   22159275        meminfo.Memused
> >     354997 ± 14%    +111.6%     751255 ±  4%  meminfo.PageTables
> >     194174           +12.8%     219047        meminfo.SReclaimable
> >     563220           +16.5%     656030        meminfo.SUnreclaim
> >     757395           +15.5%     875078        meminfo.Slab
> >     350188           +11.4%     390033        meminfo.VmallocUsed
> >   26142507            -9.8%   23588567        meminfo.max_used_kB
> >      43483 ± 14%    +119.0%      95246 ±  2%  numa-vmstat.node0.nr_page_table_pages
> >      43257 ±  3%     +12.4%      48605        numa-vmstat.node0.nr_vmalloc
> >  4.557e+08            -7.5%  4.217e+08        numa-vmstat.node0.numa_hit
> >  4.555e+08            -7.4%  4.216e+08        numa-vmstat.node0.numa_local
> >      45890 ± 13%    +109.3%      96035 ±  4%  numa-vmstat.node1.nr_page_table_pages
> >      44555 ±  4%      +9.3%      48699        numa-vmstat.node1.nr_vmalloc
> >  4.494e+08            -6.8%  4.189e+08        numa-vmstat.node1.numa_hit
> >  4.493e+08            -6.8%  4.187e+08        numa-vmstat.node1.numa_local
> >       0.16 ± 16%    +707.7%       1.30 ± 44%  perf-sched.sch_delay.avg.ms.[unknown].[unknown].[unknown].[unknown].[unknown]
> >     346.29 ± 85%   +1061.2%       4021 ± 38%  perf-sched.sch_delay.max.ms.[unknown].[unknown].[unknown].[unknown].[unknown]
> >       0.16 ± 16%    +707.7%       1.30 ± 44%  perf-sched.total_sch_delay.average.ms
> >     346.29 ± 85%   +1061.2%       4021 ± 38%  perf-sched.total_sch_delay.max.ms
> >       7.34           +58.2%      11.61 ± 13%  perf-sched.total_wait_and_delay.average.ms
> >       4478 ±  6%     +49.6%       6697 ± 20%  perf-sched.total_wait_and_delay.max.ms
> >       7.18           +43.6%      10.31 ± 10%  perf-sched.total_wait_time.average.ms
> >       4477 ±  5%     +29.7%       5809 ± 17%  perf-sched.total_wait_time.max.ms
> >       7.34           +58.2%      11.61 ± 13%  perf-sched.wait_and_delay.avg.ms.[unknown].[unknown].[unknown].[unknown].[unknown]
> >       4478 ±  6%     +49.6%       6697 ± 20%  perf-sched.wait_and_delay.max.ms.[unknown].[unknown].[unknown].[unknown].[unknown]
> >       7.18           +43.6%      10.31 ± 10%  perf-sched.wait_time.avg.ms.[unknown].[unknown].[unknown].[unknown].[unknown]
> >       4477 ±  5%     +29.7%       5809 ± 17%  perf-sched.wait_time.max.ms.[unknown].[unknown].[unknown].[unknown].[unknown]
> >    1975577            -4.0%    1896474        proc-vmstat.nr_active_anon
> >     973349            -2.6%     947803        proc-vmstat.nr_anon_pages
> >      46138            +3.1%      47546        proc-vmstat.nr_kernel_stack
> >      90193 ± 14%    +110.0%     189399 ±  4%  proc-vmstat.nr_page_table_pages
> >      48563           +12.8%      54769        proc-vmstat.nr_slab_reclaimable
> >     140817           +16.5%     164023        proc-vmstat.nr_slab_unreclaimable
> >      87646           +11.2%      97438        proc-vmstat.nr_vmalloc
> >    1975576            -4.0%    1896478        proc-vmstat.nr_zone_active_anon
> >  9.051e+08            -7.1%  8.406e+08        proc-vmstat.numa_hit
> >  9.048e+08            -7.1%  8.403e+08        proc-vmstat.numa_local
> >  9.069e+08            -7.1%  8.421e+08        proc-vmstat.pgalloc_normal
> >  3.538e+08            -7.5%  3.273e+08        proc-vmstat.pgfault
> >  9.061e+08            -7.1%  8.414e+08        proc-vmstat.pgfree
> >      29261           -10.3%      26241        sched_debug.cfs_rq:/.avg_vruntime.avg
> >       0.58 ±  5%     +13.8%       0.66 ±  4%  sched_debug.cfs_rq:/.h_nr_queued.avg
> >       0.58 ±  5%     +13.4%       0.66 ±  4%  sched_debug.cfs_rq:/.h_nr_runnable.avg
> >       4034 ± 33%     +53.7%       6200 ± 13%  sched_debug.cfs_rq:/.left_deadline.avg
> >       4034 ± 33%     +53.7%       6200 ± 13%  sched_debug.cfs_rq:/.left_vruntime.avg
> >     583523 ±  4%     +13.7%     663177 ±  4%  sched_debug.cfs_rq:/.load.avg
> >       0.58 ±  5%     +13.7%       0.66 ±  4%  sched_debug.cfs_rq:/.nr_queued.avg
> >      14.14 ± 22%     +45.5%      20.57 ± 15%  sched_debug.cfs_rq:/.removed.runnable_avg.avg
> >      67.99 ± 17%     +33.5%      90.77 ± 13%  sched_debug.cfs_rq:/.removed.runnable_avg.stddev
> >      13.66 ± 23%     +43.0%      19.54 ± 14%  sched_debug.cfs_rq:/.removed.util_avg.avg
> >      66.93 ± 17%     +31.0%      87.71 ± 14%  sched_debug.cfs_rq:/.removed.util_avg.stddev
> >       4034 ± 33%     +53.7%       6200 ± 13%  sched_debug.cfs_rq:/.right_vruntime.avg
> >     554.59 ±  2%      +8.7%     602.90 ±  3%  sched_debug.cfs_rq:/.runnable_avg.avg
> >       1553 ±  7%     +26.1%       1959 ± 17%  sched_debug.cfs_rq:/.runnable_avg.max
> >     266.15 ±  7%     +25.4%     333.85 ±  6%  sched_debug.cfs_rq:/.runnable_avg.stddev
> >       0.03 ± 76%    +526.1%       0.19 ± 31%  sched_debug.cfs_rq:/.spread.avg
> >       2.81 ± 88%    +377.6%      13.40 ± 48%  sched_debug.cfs_rq:/.spread.max
> >       0.24 ± 77%    +426.2%       1.26 ± 34%  sched_debug.cfs_rq:/.spread.stddev
> > -6.962e+10          -329.4%  1.597e+11 ± 20%  sched_debug.cfs_rq:/.sum_w_vruntime.avg
> >  1.654e+12 ±112%    +407.7%  8.398e+12 ± 18%  sched_debug.cfs_rq:/.sum_w_vruntime.max
> >     106852 ± 31%     +74.1%     185984 ± 11%  sched_debug.cfs_rq:/.sum_weight.avg
> >      29261           -10.3%      26241        sched_debug.cfs_rq:/.zero_vruntime.avg
> >     516.36 ±  3%     +85.2%     956.40 ±  3%  sched_debug.cpu.clock_task.stddev
> >     551602            -7.0%     513143        sched_debug.cpu.curr->pid.max
> >       0.59 ±  4%     +12.6%       0.67 ±  4%  sched_debug.cpu.nr_running.avg
> >      74120 ± 14%     -29.8%      52067 ± 25%  sched_debug.cpu.nr_switches.max
> >       4844 ± 18%     -36.8%       3062 ± 31%  sched_debug.cpu.nr_switches.stddev
> >       0.08 ± 47%     +83.8%       0.15 ± 20%  sched_debug.cpu.nr_uninterruptible.avg
> > 
> > 
> > 
> > 
> > Disclaimer:
> > Results have been estimated based on internal Intel analysis and are provided
> > for informational purposes only. Any difference in system hardware or software
> > design or configuration may affect actual performance.
> > 
> > 
> > -- 
> > 0-DAY CI Kernel Test Service
> > https://github.com/intel/lkp-tests/wiki
> 
> Thanks. I'll check it.

Looking at the patch [1], the regression reported by lkp [2] appears to
be caused by a lack of order-0 pages in the PCP lists,
which increases zone-locked allocations (mm_page_alloc_zone_locked).

On my reproduced setup (an x86_64 workstation), most pages freed through
free_pages_bulk() were order-2 pages (nr_pages == 4), including
vmalloc-backed stacks. With patch [1], these order-2 pages are returned to
the order-2 PCP lists, unlike commit 4aa4abf1f1 (“mm/page_alloc: optimize free_contig_range()”),
which effectively populated the order-0 PCP lists.

Since the shmem workload appears to fault memory at PAGE_SIZE granularity,
the reduced availability of order-0 pages in PCP lists seems to increase
zone-locked order-0 allocations, which may explain the regression observed by lkp.

Performance comparison (5 runs):
  - perf stat -e 'kmem:mm_page_alloc_extfrag' --filter 'alloc_order == 0' \
              -e 'kmem:mm_page_alloc_zone_locked' --filter 'order == 0' \
              -e 'kmem:mm_page_alloc' --filter 'order == 0' -- ./repro-script

Metric                               4aa4abf1f1           60ced5818f        Difference

------------------------------------------------------------------------------------------

Zone-locked Allocation Ratio (%)     46.39 ± 0.17%       48.31 ± 0.37%       +1.92 pp

  - Ratio = (mm_page_alloc_extfrag + mm_page_alloc_zone_locked) / mm_page_alloc × 100
  - Values are reported as median ± relative half-range across three runs.

The shmem test appears to handle page faults at PAGE_SIZE granularity, which seems to amplify the impact of the reduced availability of order-0 pages.


As an experiment, I modified free_pages_bulk() to free pages individually
as order-0 pages when nr_contig <= (1 << PAGE_ALLOC_COSTLY_ORDER).
This restores behavior closer to 4aa4abf1f1 and results in almost
no difference compared to that commit.

Performance comparison (5 runs)
  - ./repro-script

Metric                     4aa4abf1f1            change             Difference
----------------------------------------------------------------------------------
bogo_ops                   656,513 ± 0.34%      656,488 ± 0.23%          -25

bogo_ops/s (realtime)      10,935.95 ± 0.34%    10,935.86 ± 0.23%      -0.09

bogo_ops/s (usr+sys time)     220.31 ± 0.40%       219.30 ± 0.21%      -1.01

The differences are negligible and essentially restore the performance
observed with 4aa4abf1f1.

Given that the regression appears to be driven by a synthetic workload that
combines frequent shmem page faults with repeated stack allocation/free operations,
I do not think this is a significant concern for typical real-world workloads.

Thanks!

[1] https://lore.kernel.org/all/[email protected]/
[2] https://lore.kernel.org/r/[email protected]
[3] https://download.01.org/0day-ci/archive/20260602/[email protected]/repro-script

-----------------&<------------------
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 91bef811a771..48d9eaa1a2f3 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5206,13 +5206,24 @@ EXPORT_SYMBOL_GPL(alloc_pages_bulk_noprof);
  */
 void free_pages_bulk(struct page **page_array, unsigned long nr_pages)
 {
+       const unsigned long nr_costly = 1UL << PAGE_ALLOC_COSTLY_ORDER;
+
        while (nr_pages) {
                unsigned long nr_contig = num_pages_contiguous(page_array, nr_pages);

-               __free_contig_range(page_to_pfn(*page_array), nr_contig);
+               if (nr_contig <= nr_costly) {
+                       while (nr_contig--) {
+                               __free_page(*page_array);
+                               nr_pages--;
+                               page_array++;
+                       }
+               } else {
+                       __free_contig_range(page_to_pfn(*page_array), nr_contig);
+
+                       nr_pages -= nr_contig;
+                       page_array += nr_contig;
+               }

-               nr_pages -= nr_contig;
-               page_array += nr_contig;
                cond_resched();
        }
 }

> -- 
> Sincerely,
> Yeoreum Yun

-- 
Sincerely,
Yeoreum Yun