[patch 1/3] lib: test_vmstat: add synthetic benchmark for vm stats
From: David Rientjes
Date: Fri Jul 31 2026 - 00:26:33 EST
From: Christoph Lameter <cl@xxxxxxxxxx>
Add a synthetic benchmark that can be used to measure performance of VM
statistics. This is used to analyze any improvements or regressions in
functions that are frequently used in hot code paths.
The test is run by inserting the module: modprobe test_vmstat
The module insertion will always fail so that it is automatically
unloaded; the results are in the kernel log.
Signed-off-by: Christoph Lameter <cl@xxxxxxxxxx>
Signed-off-by: David Rientjes <rientjes@xxxxxxxxxx>
---
lib/Kconfig.debug | 10 +++++
lib/Makefile | 1 +
lib/test_vmstat.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 106 insertions(+)
create mode 100644 lib/test_vmstat.c
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1244dcac2294..6d743c8e27fa 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -3427,6 +3427,16 @@ config TEST_KEXEC_HANDOVER
If unsure, say N.
+config TEST_VMSTAT
+ tristate "VM Statistics Benchmark"
+ default n
+ help
+ A synthetic benchmark measuring the performance of VM statistics,
+ useful to analyze any improvements or regressions in functions that
+ are frequently used in hot code paths.
+
+ If unsure, say N.
+
config RATELIMIT_KUNIT_TEST
tristate "KUnit Test for correctness and stress of ratelimit" if !KUNIT_ALL_TESTS
depends on KUNIT
diff --git a/lib/Makefile b/lib/Makefile
index 7f75cc6edf94..5f3ebabd0224 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_TEST_FREE_PAGES) += test_free_pages.o
obj-$(CONFIG_TEST_REF_TRACKER) += test_ref_tracker.o
obj-$(CONFIG_TEST_OBJPOOL) += test_objpool.o
obj-$(CONFIG_TEST_KEXEC_HANDOVER) += test_kho.o
+obj-$(CONFIG_TEST_VMSTAT) += test_vmstat.o
obj-$(CONFIG_TEST_FPU) += test_fpu.o
test_fpu-y := test_fpu_glue.o test_fpu_impl.o
diff --git a/lib/test_vmstat.c b/lib/test_vmstat.c
new file mode 100644
index 000000000000..f63f439ab9d2
--- /dev/null
+++ b/lib/test_vmstat.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Test module for in-kernel synthetic vm statistics performance.
+ *
+ * execute
+ *
+ * modprobe test_vmstat
+ *
+ * to run this test
+ *
+ * (C) 2009 Linux Foundation, Christoph Lameter <cl@xxxxxxxxxx>
+ */
+
+#include <linux/jiffies.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/timex.h>
+
+#define TEST_COUNT 10000
+
+static int vmstat_test_init(void)
+{
+ unsigned int i;
+ cycles_t time1, time2, time;
+ int rem;
+ struct page *page = alloc_page(GFP_KERNEL);
+
+ pr_alert("VMstat testing\n");
+ pr_alert("=====================\n");
+ pr_alert("1. inc_zone_page_state() then dec_zone_page_state()\n");
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++)
+ inc_zone_page_state(page, NR_FREE_CMA_PAGES);
+
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ pr_alert("%i times inc_zone_page_state() ", i);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ pr_cont("-> %llu cycles ", (unsigned long long) time);
+
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++)
+ __dec_zone_page_state(page, NR_FREE_CMA_PAGES);
+
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ pr_cont("__dec_z_p_s() ");
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ pr_cont("-> %llu cycles\n", (unsigned long long) time);
+
+ pr_alert("2. inc_zone_page_state()/dec_zone_page_state()\n");
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++) {
+ inc_zone_page_state(page, NR_FREE_CMA_PAGES);
+ dec_zone_page_state(page, NR_FREE_CMA_PAGES);
+ }
+
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ pr_alert("%i times inc/dec ", i);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ pr_cont("-> %llu cycles\n", (unsigned long long) time);
+
+ pr_alert("3. count_vm_event()\n");
+ time1 = get_cycles();
+ for (i = 0; i < TEST_COUNT; i++)
+ count_vm_event(SLABS_SCANNED);
+
+ time2 = get_cycles();
+ time = time2 - time1;
+
+ count_vm_events(SLABS_SCANNED, -TEST_COUNT);
+ pr_alert("%i count_vm_events ", i);
+ time = div_u64_rem(time, TEST_COUNT, &rem);
+ pr_cont("-> %llu cycles\n", (unsigned long long) time);
+ __free_page(page);
+ return -EAGAIN; /* Fail will directly unload the module */
+}
+
+static void vmstat_test_exit(void)
+{
+ pr_alert("test exit\n");
+}
+
+module_init(vmstat_test_init)
+module_exit(vmstat_test_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christoph Lameter");
+MODULE_DESCRIPTION("VM statistics test");