From nobody Fri Oct 2 10:08:33 2026 Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DF1B4244667 for ; Sun, 2 Aug 2026 23:06:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785712012; cv=none; b=lTTp/XYNTHAb5OSCQZJjkcwq9Sl4wxNkSy05bkn/YgLL7ej03z8/BfdAavi1SZSH0u0GEunpbj62wxVj7wxKHAmznBMwQ4AKWD3x0BRxgdjQsRzF5S6C2JnRRRV9FCbTnOOaz88aUYCFa4mHW/UksAbbIBeMrzVwHlRdPj2/sWE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785712012; c=relaxed/simple; bh=mznDBMjqROCiQiHC6phlipsWYofFiYxseTb+dEevcxM=; h=Date:From:To:cc:Subject:In-Reply-To:Message-ID:References: MIME-Version:Content-Type; b=LPSuPD/MInkhjQL+r1Nqc2Kdl3PeWmwDl4Q0t+EVvmdg/+MLGWwTL5nsUyp6E5S1yCLmQqZeH2hbL2AwvxXYxMF9a6cZkm0JXblMaWmR+n4WXJpMfc7x3PqDGAbJPSdxWyWxHg2ld0d0hQIFT843wcdkzaCIxA3QIM5uMa9JMaM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=qrCayYCd; arc=none smtp.client-ip=209.85.214.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qrCayYCd" Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-2ccdf36f63dso84145ad.0 for ; Sun, 02 Aug 2026 16:06:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1785712010; x=1786316810; darn=vger.kernel.org; h=content-type:mime-version:references:message-id:in-reply-to:subject :cc:to:from:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=5l4odDXQoSJW0+BHeNDPiNY7HseZAOv5KH97z8YXnGI=; b=qrCayYCdc8V79fmPJMwm2/fcTBoBOrS68cEYw5CMVUiGrqjAAdHjSGGEw4MtvwHRN/ VfDhCABQzq3nfsEYJvsO3DKlGlPPBV53TFu7gHLkmhSaV86zNAX7Iyn3tnzkIj8mhLBi xDEf3/1o31u9d8kGvCQ9jzEel2DvDvGPWlX7pDoFi5J2HjYPjHrG0yNBbGwdwGfaqnC1 nT/ciGgCZefduElB3QXOeag4jxU8OSyeqTDDUuWMItYSBQJ2m8IlnprMOQdgso4Jicy1 uHD+woYmPPLUJ+oMOsag7EBDkeBrpOf2PvRC7f7qzufdETJHZ2P8WI5nTH3FyxymecyF xACQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785712010; x=1786316810; h=content-type:mime-version:references:message-id:in-reply-to:subject :cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=5l4odDXQoSJW0+BHeNDPiNY7HseZAOv5KH97z8YXnGI=; b=boB4Zpd1n+fuiIfeMjLTo9doTCUxsiq9E710gFCTyJCjCslMkJXtL3VXinxLypTDP7 oveN30VVhSp4Lyph6mZ60MD9PgKzZ9a3vTngMnYxHkpEpubhk1xAlw8ZNIbeS0yWwU0e tqELhPqHTlEtzPLihFfxR7rpUO7TXdgf2n/lwuICroHvNL/VkbPXt0naCvMUdhMpmPdu a0OVcuMScCrfbJ2K3F4RqVy7zvRIwly7lIefMnJ+SMvMH2DDqMoWDM1OKzG1sJhONFFV evKRUX6zsH5kZwyO+WRYqIpkVFg1Ate3cTSAR8v68ChHrxzOW/VITb70LO5X2gmQOjJy kGuw== X-Forwarded-Encrypted: i=1; AHgh+Ro3cqioRRKkbTF8OCQwEs5kprz2S6aTKeLdfFg6XqKd9MezJNlr8C935+dJrAs2xPQMmAuQYfHJO/43WNY=@vger.kernel.org X-Gm-Message-State: AOJu0Yz0y8rpJuK/nCEPsPDgiVNuyvyUJuFxo2R2SZr0nsGjkUlWY/1i AmvmkdNsuMkg9vYubk8N0vuFYOCP/fYvNJF/gOp/jojPIwj2WraTitZX6pymx6PMuA== X-Gm-Gg: AR+sD108VkT8jwn6rb5M7dAodVHHISjXXCLCpHi4uWaJ8M/r0Jus4tALTx4B2q9l1t7 l5W3wKVTCb+UeMsqwv2mUG25qY5XPJNNAK1TeMawV9xcHuvvCe6vAV69z+zLOl65b4a/+IbtnZ4 x5InO+77UyzLT27MzZwl4DCCvX5mrqubJ3FSqB7terPUy6lHDOuhtZpT/uLCHsWE8AsDnExrVAa 0pNamGG++eKY+M/o8nhrkyxsE0+BCZ8SZJ4hsowCXgipC1JN/4dBBM1v9SU8NvPdxaf1/9qnbdx UCs2IJQE8eF4/GLxvw4cI9cBOp+Rf+T1qihEuBCvUq9yo0vt7zft0+uF61wbwuyY9nwZVAil87v bgzG9WOwrfIEJvSfnFl2Mh8W8gn0WyM5HFizsDPXOGf5EAce8BFn6PwLkT1yR7Xw8wwizqT3Zhf RRzPfUHaAknRHKc7ps9l+hFjUb5inFqbIpWL8ITkSwEX/+9UIKFdSYjhwC7hYlxFPtGjVvHrl02 FxXylfe75rveTLqacvjYGtkvuBCMI48Yw2uwkq7QEpjDmJNTygFyxUetU7H3vYEjWYtfi4LingY rLaZttYcqzOUSSY= X-Received: by 2002:a17:903:1205:b0:2cc:80b9:3a1 with SMTP id d9443c01a7336-2d0573c0ca7mr6072905ad.13.1785712009361; Sun, 02 Aug 2026 16:06:49 -0700 (PDT) Received: from [2a00:79e0:2eb4:9:b3ef:da16:936a:c7c9] ([2a00:79e0:2eb4:9:b3ef:da16:936a:c7c9]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84edc2d7b97sm2853952b3a.43.2026.08.02.16.06.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 02 Aug 2026 16:06:48 -0700 (PDT) Date: Sun, 2 Aug 2026 16:06:47 -0700 (PDT) From: David Rientjes To: Andrew Morton , David Hildenbrand , Christoph Lameter cc: Vlastimil Babka , Mathieu Desnoyers , linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [patch v2] lib: test_vmstat: add synthetic benchmark for vm stats In-Reply-To: Message-ID: <94068447-f9c5-ba84-73be-bf492277b9b3@google.com> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Christoph Lameter 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 Signed-off-by: David Rientjes --- v2: - added bash wrapper to ksft per David - integrated into ksft - added MAINTAINERS entry per David - fixed alloc_page() error code per Usama Adding single test for now to solicit feedback before updating the other two. MAINTAINERS | 1 + lib/Kconfig.debug | 10 +++ lib/Makefile | 1 + lib/test_vmstat.c | 100 ++++++++++++++++++++++ tools/testing/selftests/mm/Makefile | 2 + tools/testing/selftests/mm/config | 1 + tools/testing/selftests/mm/ksft_vmstat.sh | 4 + tools/testing/selftests/mm/run_vmtests.sh | 5 ++ tools/testing/selftests/mm/test_vmstat.sh | 71 +++++++++++++++ 9 files changed, 195 insertions(+) create mode 100644 lib/test_vmstat.c create mode 100755 tools/testing/selftests/mm/ksft_vmstat.sh create mode 100755 tools/testing/selftests/mm/test_vmstat.sh diff --git a/MAINTAINERS b/MAINTAINERS index 5114e6db7307..c76514d6c503 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17004,6 +17004,7 @@ F: mm/sparse.c F: mm/util.c F: mm/vmpressure.c F: mm/vmstat.c +F: lib/test_vmstat.c N: include\/linux\/page[-_][a-zA-Z]* =20 MEMORY MANAGEMENT - EXECMEM 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 =20 If unsure, say N. =20 +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_A= LL_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) +=3D test_free_pages.o obj-$(CONFIG_TEST_REF_TRACKER) +=3D test_ref_tracker.o obj-$(CONFIG_TEST_OBJPOOL) +=3D test_objpool.o obj-$(CONFIG_TEST_KEXEC_HANDOVER) +=3D test_kho.o +obj-$(CONFIG_TEST_VMSTAT) +=3D test_vmstat.o =20 obj-$(CONFIG_TEST_FPU) +=3D test_fpu.o test_fpu-y :=3D 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..ee4872a4c82d --- /dev/null +++ b/lib/test_vmstat.c @@ -0,0 +1,100 @@ +// 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 + */ + +#include +#include +#include +#include +#include +#include + +#define TEST_COUNT 10000 + +static int vmstat_test_init(void) +{ + unsigned int i; + cycles_t time1, time2, time; + int rem; + struct page *page =3D alloc_page(GFP_KERNEL); + + if (!page) + return -ENOMEM; + + pr_alert("VMstat testing\n"); + pr_alert("=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= \n"); + pr_alert("1. inc_zone_page_state() then dec_zone_page_state()\n"); + time1 =3D get_cycles(); + for (i =3D 0; i < TEST_COUNT; i++) + inc_zone_page_state(page, NR_FREE_CMA_PAGES); + + time2 =3D get_cycles(); + time =3D time2 - time1; + + pr_alert("%i times inc_zone_page_state() ", i); + time =3D div_u64_rem(time, TEST_COUNT, &rem); + pr_cont("-> %llu cycles ", (unsigned long long) time); + + time1 =3D get_cycles(); + for (i =3D 0; i < TEST_COUNT; i++) + dec_zone_page_state(page, NR_FREE_CMA_PAGES); + + time2 =3D get_cycles(); + time =3D time2 - time1; + + pr_cont("__dec_z_p_s() "); + time =3D 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 =3D get_cycles(); + for (i =3D 0; i < TEST_COUNT; i++) { + inc_zone_page_state(page, NR_FREE_CMA_PAGES); + dec_zone_page_state(page, NR_FREE_CMA_PAGES); + } + + time2 =3D get_cycles(); + time =3D time2 - time1; + + pr_alert("%i times inc/dec ", i); + time =3D div_u64_rem(time, TEST_COUNT, &rem); + pr_cont("-> %llu cycles\n", (unsigned long long) time); + + pr_alert("3. count_vm_event()\n"); + time1 =3D get_cycles(); + for (i =3D 0; i < TEST_COUNT; i++) + count_vm_event(SLABS_SCANNED); + + time2 =3D get_cycles(); + time =3D time2 - time1; + + count_vm_events(SLABS_SCANNED, -TEST_COUNT); + pr_alert("%i count_vm_events ", i); + time =3D div_u64_rem(time, TEST_COUNT, &rem); + pr_cont("-> %llu cycles\n", (unsigned long long) time); + __free_page(page); + + /* Fail will directly unload the module */ + return IS_BUILTIN(CONFIG_TEST_VMSTAT) ? 0 : -EAGAIN; +} + +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"); diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/= mm/Makefile index e6df968f0971..0d386c8b83b7 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -173,8 +173,10 @@ TEST_PROGS +=3D ksft_thp.sh TEST_PROGS +=3D ksft_userfaultfd.sh TEST_PROGS +=3D ksft_vma_merge.sh TEST_PROGS +=3D ksft_vmalloc.sh +TEST_PROGS +=3D ksft_vmstat.sh =20 TEST_FILES :=3D test_vmalloc.sh +TEST_FILES :=3D test_vmstat.sh TEST_FILES +=3D test_hmm.sh TEST_FILES +=3D va_high_addr_switch.sh TEST_FILES +=3D charge_reserved_hugetlb.sh diff --git a/tools/testing/selftests/mm/config b/tools/testing/selftests/mm= /config index 06f78bd232e2..16e02a2cb2a1 100644 --- a/tools/testing/selftests/mm/config +++ b/tools/testing/selftests/mm/config @@ -2,6 +2,7 @@ CONFIG_SYSVIPC=3Dy CONFIG_USERFAULTFD=3Dy CONFIG_PTE_MARKER_UFFD_WP=3Dy CONFIG_TEST_VMALLOC=3Dm +CONFIG_TEST_VMSTAT=3Dm CONFIG_DEVICE_PRIVATE=3Dy CONFIG_TEST_HMM=3Dm CONFIG_GUP_TEST=3Dy diff --git a/tools/testing/selftests/mm/ksft_vmstat.sh b/tools/testing/self= tests/mm/ksft_vmstat.sh new file mode 100755 index 000000000000..4e47112f9925 --- /dev/null +++ b/tools/testing/selftests/mm/ksft_vmstat.sh @@ -0,0 +1,4 @@ +#!/bin/sh -e +# SPDX-License-Identifier: GPL-2.0 + +./run_vmtests.sh -t vmstat diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/self= tests/mm/run_vmtests.sh index 8c296dedf047..c5416eda4c2e 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -47,6 +47,8 @@ separated by spaces: tests for very large virtual address space - vmalloc vmalloc smoke tests +- vmstat + vmstat performance test - hmm hmm smoke tests - madv_guard @@ -338,6 +340,9 @@ fi # VADDR64 # vmalloc stability smoke test CATEGORY=3D"vmalloc" run_test bash ./test_vmalloc.sh smoke =20 +# vmstat performance test +CATEGORY=3D"vmstat" run_test bash ./test_vmstat.sh performance + CATEGORY=3D"mremap" run_test ./mremap_dontunmap =20 CATEGORY=3D"hmm" run_test bash ./test_hmm.sh smoke diff --git a/tools/testing/selftests/mm/test_vmstat.sh b/tools/testing/self= tests/mm/test_vmstat.sh new file mode 100755 index 000000000000..a4fc7f7fec16 --- /dev/null +++ b/tools/testing/selftests/mm/test_vmstat.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# This is a test script for the kernel test module to measure performance = of VM +# statistics. It simply loads the kernel module. + +TEST_NAME=3D"vmstat" +DRIVER=3D"test_${TEST_NAME}" + +# Kselftest framework requirement - SKIP code is 4. +ksft_skip=3D4 + +check_test_requirements() +{ + uid=3D$(id -u) + if [ $uid -ne 0 ]; then + echo "$0: Must be run as root" + exit $ksft_skip + fi + + if ! which modprobe > /dev/null 2>&1; then + echo "$0: You need modprobe installed" + exit $ksft_skip + fi + + if ! modinfo $DRIVER > /dev/null 2>&1; then + echo "$0: You must have the following enabled in your kernel:" + echo "CONFIG_TEST_VMSTAT=3Dm" + exit $ksft_skip + fi +} + +run_performance_check() +{ + echo "Run performance tests to evaluate how fast vmstat is." + + modprobe $DRIVER > /dev/null 2>&1 + echo "Done." + echo "Check the kernel message buffer to see the summary." +} + +usage() +{ + echo -n "Usage: $0 performance" + echo + echo "Example usage:" + echo + echo "# Shows help message" + echo "./${DRIVER}.sh" + echo + echo "# Performance analysis" + echo "./${DRIVER}.sh performance" + echo + exit 0 +} + +function run_test() +{ + if [ $# -eq 0 ]; then + usage + else + if [[ "$1" =3D "performance" ]]; then + run_performance_check + fi + fi +} + +check_test_requirements +run_test $@ + +exit 0