From: Tamir Duberstein tamird@gmail.com
Add CONFIG_BITMAP_BENCHMARK to build benchmarks separately from unit tests. The new module is marked authored by the author of commit 991e5583647d ("lib/test_bitmap: add tests for bitmap_{read,write}()") which added these benchmarks.
Extract duplicated code between `test_bitmap_{read,write}_perf`.
Cc: Alexander Potapenko glider@google.com Signed-off-by: Tamir Duberstein tamird@gmail.com --- MAINTAINERS | 1 + lib/Kconfig.debug | 8 +++++ lib/Makefile | 1 + lib/bitmap_benchmark.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/test_bitmap.c | 50 ---------------------------- 5 files changed, 99 insertions(+), 50 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS index 5b11839cba9d..4ddaef15b408 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4426,6 +4426,7 @@ F: include/uapi/linux/bits.h F: include/vdso/bits.h F: lib/bitmap-str.c F: lib/bitmap.c +F: lib/bitmap_benchmark.c F: lib/cpumask.c F: lib/find_bit.c F: lib/find_bit_benchmark.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ba36939fda79..60434b31a940 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2492,6 +2492,14 @@ config FFS_KUNIT_TEST config TEST_KSTRTOX tristate "Test kstrto*() family of functions at runtime"
+config BITMAP_BENCHMARK + tristate "Benchmark bitmap_*() family of functions" + help + This builds the "bitmap_benchmark_test" module that measure bitmap_*() + family of functions performance. + + If unsure, say N. + config TEST_BITMAP tristate "Test bitmap_*() family of functions at runtime" help diff --git a/lib/Makefile b/lib/Makefile index aaf677cf4527..892cb3152b65 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -61,6 +61,7 @@ obj-y += string_helpers.o obj-y += hexdump.o obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o obj-y += kstrtox.o +obj-$(CONFIG_BITMAP_BENCHMARK) += bitmap_benchmark.o obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o obj-$(CONFIG_FIND_BIT_BENCHMARK_RUST) += find_bit_benchmark_rust.o obj-$(CONFIG_TEST_BPF) += test_bpf.o diff --git a/lib/bitmap_benchmark.c b/lib/bitmap_benchmark.c new file mode 100644 index 000000000000..47f4cea4e831 --- /dev/null +++ b/lib/bitmap_benchmark.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Benchmarks for bitmap API. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/bitmap.h> +#include <linux/init.h> +#include <linux/ktime.h> +#include <linux/module.h> +#include <linux/printk.h> + +/* + * Test bitmap should be big enough to include the cases when start is not in + * the first word, and start+nbits lands in the following word. + */ +#define TEST_BIT_LEN (1000) + +typedef void (*bitmap_bench_fn)(unsigned long *bitmap, unsigned long i, unsigned long nbits); + +static void __init bench_bitmap(bitmap_bench_fn bench_fn, const char *name) +{ + DECLARE_BITMAP(bitmap, TEST_BIT_LEN); + unsigned int cnt, nbits, i; + ktime_t time; + + bitmap_fill(bitmap, TEST_BIT_LEN); + time = ktime_get(); + for (cnt = 0; cnt < 5; cnt++) { + for (nbits = 1; nbits <= BITS_PER_LONG; nbits++) { + for (i = 0; i < TEST_BIT_LEN; i++) { + if (i + nbits > TEST_BIT_LEN) + break; + bench_fn(bitmap, i, nbits); + } + } + } + time = ktime_get() - time; + pr_info("Time spent in %s:\t%llu\n", name, time); +} + +#undef TEST_BIT_LEN + +static inline void bitmap_read_bench(unsigned long *bitmap, unsigned long i, unsigned long nbits) +{ + unsigned long val; + /* + * Prevent the compiler from optimizing away the + * bitmap_read() by using its value. + */ + WRITE_ONCE(val, bitmap_read(bitmap, i, nbits)); +} + +static void __init test_bitmap_read_perf(void) +{ + bench_bitmap(bitmap_read_bench, __func__); +} + +static inline void bitmap_write_bench(unsigned long *bitmap, unsigned long i, unsigned long nbits) +{ + unsigned long val = 0xfeedface; + + bitmap_write(bitmap, val, i, nbits); +} + +static void __init test_bitmap_write_perf(void) +{ + bench_bitmap(bitmap_write_bench, __func__); +} + +static int __init bitmap_benchmark_init(void) +{ + test_bitmap_read_perf(); + test_bitmap_write_perf(); + + return 0; +} +module_init(bitmap_benchmark_init); + +static void __exit bitmap_benchmark_exit(void) +{ + pr_info("Unloaded\n"); +} +module_exit(bitmap_benchmark_exit); + +MODULE_AUTHOR("Alexander Potapenko glider@google.com"); +MODULE_DESCRIPTION("Benchmarks for bitmap API"); +MODULE_LICENSE("GPL"); diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c index c83829ef557f..f728b6485c88 100644 --- a/lib/test_bitmap.c +++ b/lib/test_bitmap.c @@ -1372,54 +1372,6 @@ static void __init test_bitmap_read_write(void) test_bitmap_write_helper(pattern[pi]); }
-static void __init test_bitmap_read_perf(void) -{ - DECLARE_BITMAP(bitmap, TEST_BIT_LEN); - unsigned int cnt, nbits, i; - unsigned long val; - ktime_t time; - - bitmap_fill(bitmap, TEST_BIT_LEN); - time = ktime_get(); - for (cnt = 0; cnt < 5; cnt++) { - for (nbits = 1; nbits <= BITS_PER_LONG; nbits++) { - for (i = 0; i < TEST_BIT_LEN; i++) { - if (i + nbits > TEST_BIT_LEN) - break; - /* - * Prevent the compiler from optimizing away the - * bitmap_read() by using its value. - */ - WRITE_ONCE(val, bitmap_read(bitmap, i, nbits)); - } - } - } - time = ktime_get() - time; - pr_info("Time spent in %s:\t%llu\n", __func__, time); -} - -static void __init test_bitmap_write_perf(void) -{ - DECLARE_BITMAP(bitmap, TEST_BIT_LEN); - unsigned int cnt, nbits, i; - unsigned long val = 0xfeedface; - ktime_t time; - - bitmap_zero(bitmap, TEST_BIT_LEN); - time = ktime_get(); - for (cnt = 0; cnt < 5; cnt++) { - for (nbits = 1; nbits <= BITS_PER_LONG; nbits++) { - for (i = 0; i < TEST_BIT_LEN; i++) { - if (i + nbits > TEST_BIT_LEN) - break; - bitmap_write(bitmap, val, i, nbits); - } - } - } - time = ktime_get() - time; - pr_info("Time spent in %s:\t%llu\n", __func__, time); -} - #undef TEST_BIT_LEN
static void __init selftest(void) @@ -1440,8 +1392,6 @@ static void __init selftest(void) test_bitmap_print_buf(); test_bitmap_const_eval(); test_bitmap_read_write(); - test_bitmap_read_perf(); - test_bitmap_write_perf();
test_find_nth_bit(); test_for_each_set_bit();