diff --git a/lib/raid/Kconfig b/lib/raid/Kconfig index 978cd6ba08ac..c4eeb7c716c8 100644 --- a/lib/raid/Kconfig +++ b/lib/raid/Kconfig @@ -29,6 +29,12 @@ config XOR_KUNIT_TEST This is intended to help people writing architecture-specific optimized versions. If unsure, say N. +config XOR_BENCHMARK + bool "Benchmark for xor_gen" + depends on XOR_KUNIT_TEST + help + Include benchmarks in the KUnit test suite for xor_gen. + config RAID6_PQ tristate diff --git a/lib/raid/xor/tests/xor_kunit.c b/lib/raid/xor/tests/xor_kunit.c index 659ae3edbc25..1fb30b2c7c47 100644 --- a/lib/raid/xor/tests/xor_kunit.c +++ b/lib/raid/xor/tests/xor_kunit.c @@ -125,8 +125,70 @@ static void xor_test(struct kunit *test) } } +static void xor_benchmark(struct kunit *test) +{ + static const unsigned int nr_to_test[] = { + 4, 5, 6, 7, 8, 10, 12, 15, 16, 32, + }; + static const unsigned int len_to_test[] = { + SZ_4K, SZ_16K, + }; + unsigned int i, j, l; + u64 t; + + if (!IS_ENABLED(CONFIG_XOR_BENCHMARK)) + kunit_skip(test, "not enabled"); + + /* warm-up */ + for (i = 0; i < ARRAY_SIZE(nr_to_test); i++) { + for (j = 0; j < ARRAY_SIZE(len_to_test); j++) { + for (l = 0; l < 10; l++) { + xor_gen(test_dest, test_buffers, nr_to_test[i], + len_to_test[j]); + } + } + } + + /* + * Preferably this would be a loop over len_to_test, but the kunit + * logging always adds a newline to each logged format string. + */ + static_assert(ARRAY_SIZE(len_to_test) == 2); + kunit_info(test, " \t%5u bytes\t%5u bytes\n", + len_to_test[0], len_to_test[1]); + + for (i = 0; i < ARRAY_SIZE(nr_to_test); i++) { + unsigned int nr = nr_to_test[i]; + u64 speed[ARRAY_SIZE(len_to_test)]; + + KUNIT_ASSERT_LE(test, nr, XOR_KUNIT_MAX_BUFFERS); + + for (j = 0; j < ARRAY_SIZE(len_to_test); j++) { + unsigned int len = len_to_test[j]; + const unsigned long num_iters = 1000; + + KUNIT_ASSERT_GT(test, len, 0); + KUNIT_ASSERT_LE(test, len, XOR_KUNIT_MAX_BYTES); + + preempt_disable(); + t = ktime_get_ns(); + for (l = 0; l < num_iters; l++) + xor_gen(test_dest, test_buffers, nr, len); + t = max(ktime_get_ns() - t, 1); + preempt_enable(); + + speed[j] = div64_u64((u64)len * num_iters * nr, t); + } + + static_assert(ARRAY_SIZE(len_to_test) == 2); + kunit_info(test, "%3u disks:\t%5llu GB/s\t%5llu GB/s\n", + nr, speed[0], speed[1]); + } +} + static struct kunit_case xor_test_cases[] = { KUNIT_CASE(xor_test), + KUNIT_CASE(xor_benchmark), {}, };