Re: [patch 1/3] lib: test_vmstat: add synthetic benchmark for vm stats
From: Usama Arif
Date: Sat Aug 01 2026 - 09:20:55 EST
On Thu, 30 Jul 2026 21:26:23 -0700 (PDT) David Rientjes <rientjes@xxxxxxxxxx> wrote:
> 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);
> +
Good to check page != NULL before using it below.
> + 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);
Why use inc_zone_page_state() but the __ variant for decrement?
Checking the 2 functions, __dec_zone_page_state() might cause
problems if preemption is enabled?
> +
> + 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");
>
>