From: David Laight <david.laight.linux@gmail.com>
To: Petr Mladek <pmladek@suse.com>, Kees Cook <kees@kernel.org>,
David Laight <david.laight.linux@gmail.com>,
linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org,
bpf@vger.kernel.org, Jim Cromie <jim.cromie@gmail.com>,
Lorenzo Stoakes <ljs@kernel.org>
Cc: Luis Chamberlain <mcgrof@kernel.org>,
Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>,
Steven Rostedt <rostedt@goodmis.org>,
Andrii Nakryiko <andrii@kernel.org>,
Samuel Wu <wusamuel@google.com>,
linux-kselftest@vger.kernel.org
Subject: [PATCH v3 next 06/13] kallsyms: Improve selftest test_perf_kallsyms_lookup_name() output
Date: Wed, 11 Nov 2026 11:59:04 +0000 [thread overview]
Message-ID: <20261111115911.1142000-7-david.laight.linux@gmail.com> (raw)
In-Reply-To: <20261111115911.1142000-1-david.laight.linux@gmail.com>
- Improve the test stability/reproducability by taking the faster of
two calls to kallsyms_lookup_name().
- Check that kallsyms_lookup_name() returns the expected address
unless the symbol is duplicated.
- Report the names of the min/max symbols.
- Output an 8 line 64 entry histogram of the times taken.
- This shows there is a reasonably normal distribution with a small
number of much slower outliers that don't really affect the average.
Additionally:
- Add a very long symbol to check the handling of two byte lengths.
- Do the test_perf_kallsyms_lookup_name() last because it can take long
enough that the CPU frequency changes and the times reported by the
other tests can change.
- Mark the 4 test functions noinline_for_stack since they all have a
quite large on-stack structure.
Example output (after all these patches)
kallsyms_on_each_symbol() traverse all: 7742950 ns
kallsyms_on_each_match_symbol() traverse all: 951 ns
kallsyms_lookup_name() looked up 123312 symbols, average 200 ns
fastest 60 ns (_rs.0)
slowest 662 ns (The_time_has_come_the_Walrus_said_To_talk_of_many_things_Of_sho)
Distribution, 20ns per column, 2916 counts per *:
| **
| ****
| ****
| ****
| ******
| *******
| *********
| ****************** ** * * *
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---
v3:
- Previously patch 3.
- Fix build when CONFIG_KALLSYMS_ALL set.
- Fix compression ratio print (50.05% not 50.5%)
kernel/kallsyms_selftest.c | 169 ++++++++++++++++++++++++++++---------
1 file changed, 127 insertions(+), 42 deletions(-)
diff --git a/kernel/kallsyms_selftest.c b/kernel/kallsyms_selftest.c
index 0db79237fe54..f7fef70ed2c8 100644
--- a/kernel/kallsyms_selftest.c
+++ b/kernel/kallsyms_selftest.c
@@ -22,6 +22,8 @@
#define MAX_NUM_OF_RECORDS 64
+#define HISTOGRAM_BUCKETS 64
+#define HISTOGRAM_RESOLUTION 10
struct test_stat {
int min;
@@ -29,39 +31,60 @@ struct test_stat {
int save_cnt;
int real_cnt;
int perf;
- u64 sum;
char *name;
unsigned long addr;
unsigned long addrs[MAX_NUM_OF_RECORDS];
};
+struct lookup_name_info {
+ unsigned int count;
+ unsigned int min;
+ unsigned int max;
+ u64 sum;
+ char min_name[64];
+ char max_name[64];
+ unsigned int histogram[HISTOGRAM_BUCKETS];
+ unsigned int scale;
+};
+
struct test_item {
char *name;
unsigned long addr;
};
-#define ITEM_FUNC(s) \
- { \
- .name = #s, \
- .addr = (unsigned long)s, \
- }
-
-#define ITEM_DATA(s) \
+#define _TEST_ITEM(s) \
{ \
.name = #s, \
.addr = (unsigned long)&s, \
}
+#define TEST_ITEM(s) _TEST_ITEM(s)
static int kallsyms_test_var_bss_static;
static int kallsyms_test_var_data_static = 1;
int kallsyms_test_var_bss;
int kallsyms_test_var_data = 1;
+/* This is 509 characters, compresses to about 330 */
+#define kallsyms_very_long_name \
+The_time_has_come_the_Walrus_said_To_talk_of_many_things\
+_Of_shoes_and_ships_and_sealing_wax_Of_cabbages_and_kings\
+_And_why_the_sea_is_boiling_hot_And_whether_pigs_have_wings\
+\
+_O_Oysters_said_the_Carpenter_Youve_had_a_pleasant_run\
+_Shall_we_be_trotting_home_again_But_answer_came_there_none\
+_And_this_was_scarcely_odd_because_Theyd_eaten_every_one\
+\
+_The_moon_was_shining_sulkily_Because_she_thought_the_sun\
+_Had_got_no_business_to_be_there_After_the_day_was_done\
+_Its_very_rude_of_him_she_said_To_come_and_spoil_the_fun
+
+static int kallsyms_very_long_name = 1;
+
static int kallsyms_test_func_static(void)
{
kallsyms_test_var_bss_static++;
- kallsyms_test_var_data_static++;
+ kallsyms_test_var_data_static += kallsyms_very_long_name;
return 0;
}
@@ -79,16 +102,17 @@ __weak int kallsyms_test_func_weak(void)
}
static struct test_item test_items[] = {
- ITEM_FUNC(kallsyms_test_func_static),
- ITEM_FUNC(kallsyms_test_func),
- ITEM_FUNC(kallsyms_test_func_weak),
- ITEM_FUNC(vmalloc_noprof),
- ITEM_FUNC(vfree),
+ TEST_ITEM(kallsyms_test_func_static),
+ TEST_ITEM(kallsyms_test_func),
+ TEST_ITEM(kallsyms_test_func_weak),
+ TEST_ITEM(vmalloc_noprof),
+ TEST_ITEM(vfree),
#ifdef CONFIG_KALLSYMS_ALL
- ITEM_DATA(kallsyms_test_var_bss_static),
- ITEM_DATA(kallsyms_test_var_data_static),
- ITEM_DATA(kallsyms_test_var_bss),
- ITEM_DATA(kallsyms_test_var_data),
+ TEST_ITEM(kallsyms_test_var_bss_static),
+ TEST_ITEM(kallsyms_test_var_data_static),
+ TEST_ITEM(kallsyms_very_long_name),
+ TEST_ITEM(kallsyms_test_var_bss),
+ TEST_ITEM(kallsyms_test_var_data),
#endif
};
@@ -101,7 +125,7 @@ static int stat_symbol_len(void *data, const char *name, unsigned long addr)
return 0;
}
-static void test_kallsyms_compression_ratio(void)
+static noinline_for_stack void test_kallsyms_compression_ratio(void)
{
u32 pos, off, len, num;
u32 ratio, total_size, total_len = 0;
@@ -148,43 +172,104 @@ static void test_kallsyms_compression_ratio(void)
pr_info("| nr_symbols | compressed size | original size | ratio(%%) |\n");
pr_info("|---------------------------------------------------------|\n");
ratio = (u32)div_u64(10000ULL * total_size, total_len);
- pr_info("| %10d | %10d | %10d | %2d.%-2d |\n",
+ pr_info("| %10d | %10d | %10d | %2d.%02d |\n",
kallsyms_num_syms, total_size, total_len, ratio / 100, ratio % 100);
pr_info(" ---------------------------------------------------------\n");
}
+static int is_duplicate(void *data, unsigned long addr)
+{
+ return (*(int *)data)++;
+}
+
static int lookup_name(void *data, const char *name, unsigned long addr)
{
- u64 t0, t1, t;
- struct test_stat *stat = (struct test_stat *)data;
+ struct lookup_name_info *info = data;
+ unsigned int i, t0, t1, t;
+ unsigned long got_addr;
+ /* Improve the stability by taking the fastest of two calls. */
t0 = ktime_get_ns();
(void)kallsyms_lookup_name(name);
t1 = ktime_get_ns();
-
t = t1 - t0;
- if (t < stat->min)
- stat->min = t;
+ got_addr = kallsyms_lookup_name(name);
+ t0 = ktime_get_ns();
+ if (t0 - t1 < t)
+ t = t0 - t1;
- if (t > stat->max)
- stat->max = t;
+ if (addr != got_addr) {
+ int c = 0;
- stat->real_cnt++;
- stat->sum += t;
+ if (!kallsyms_on_each_match_symbol(is_duplicate, name, &c)) {
+ pr_info("got %ld not %ld for %s\n", got_addr, addr, name);
+ return 1;
+ }
+ }
+
+ info->count++;
+ info->sum += t;
+
+ if (t < info->min) {
+ info->min = t;
+ strscpy(info->min_name, name);
+ }
+
+ if (t > info->max) {
+ info->max = t;
+ strscpy(info->max_name, name);
+ }
+
+ /* Create a histogram of the times */
+ t = (t / HISTOGRAM_RESOLUTION) >> info->scale;
+ while (t >= HISTOGRAM_BUCKETS) {
+ t >>= 1;
+ info->scale++;
+ for (i = 0; i < HISTOGRAM_BUCKETS / 2; i++)
+ info->histogram[i] = info->histogram[2 * i] + info->histogram[2 * i + 1];
+ for (; i < HISTOGRAM_BUCKETS; i++)
+ info->histogram[i] = 0;
+ }
+ info->histogram[t]++;
return 0;
}
-static void test_perf_kallsyms_lookup_name(void)
+static noinline_for_stack void test_perf_kallsyms_lookup_name(void)
{
- struct test_stat stat;
-
- memset(&stat, 0, sizeof(stat));
- stat.min = INT_MAX;
- kallsyms_on_each_symbol(lookup_name, &stat);
- pr_info("kallsyms_lookup_name() looked up %d symbols\n", stat.real_cnt);
- pr_info("The time spent on each symbol is (ns): min=%d, max=%d, avg=%lld\n",
- stat.min, stat.max, div_u64(stat.sum, stat.real_cnt));
+ struct lookup_name_info info;
+ unsigned int idx, scale, row;
+ char line[HISTOGRAM_BUCKETS];
+ int len;
+
+ memset(&info, 0, sizeof(info));
+ info.min = ~0u;
+ kallsyms_on_each_symbol(lookup_name, &info);
+ pr_info("kallsyms_lookup_name() looked up %d symbols, average %lld ns\n",
+ info.count, div_u64(info.sum, info.count));
+ pr_info("\tfastest %u ns (%s)\n", info.min, info.min_name);
+ pr_info("\tslowest %u ns (%s)\n", info.max, info.max_name);
+
+ scale = 0;
+ for (idx = 0; idx < HISTOGRAM_BUCKETS; idx++) {
+ if (scale < info.histogram[idx])
+ scale = info.histogram[idx];
+ }
+ row = 8;
+ scale /= row;
+ pr_info("\tDistribution, %uns per column, %u counts per *:\n",
+ HISTOGRAM_RESOLUTION << info.scale, scale);
+ while (row--) {
+ memset(line, ' ', sizeof(line));
+ len = 0;
+ for (idx = 0; idx < HISTOGRAM_BUCKETS; idx++) {
+ if (info.histogram[idx] > row * scale) {
+ len = idx + 1;
+ line[idx] = '*';
+ }
+ }
+ pr_info("\t|%.*s\n", len, line);
+ }
}
static int find_symbol(void *data, const char *name, unsigned long addr)
@@ -207,7 +292,7 @@ static int find_symbol(void *data, const char *name, unsigned long addr)
return 0;
}
-static void test_perf_kallsyms_on_each_symbol(void)
+static noinline_for_stack void test_perf_kallsyms_on_each_symbol(void)
{
u64 t0, t1;
struct test_stat stat;
@@ -240,7 +325,7 @@ static int match_symbol(void *data, unsigned long addr)
return 0;
}
-static void test_perf_kallsyms_on_each_match_symbol(void)
+static noinline_for_stack void test_perf_kallsyms_on_each_match_symbol(void)
{
u64 t0, t1;
struct test_stat stat;
@@ -254,7 +339,7 @@ static void test_perf_kallsyms_on_each_match_symbol(void)
pr_info("kallsyms_on_each_match_symbol() traverse all: %lld ns\n", t1 - t0);
}
-static int test_kallsyms_basic_function(void)
+static noinline_for_stack int test_kallsyms_basic_function(void)
{
int i, j, ret;
int next = 0, nr_failed = 0;
@@ -425,9 +510,9 @@ static int test_entry(void *p)
}
test_kallsyms_compression_ratio();
- test_perf_kallsyms_lookup_name();
test_perf_kallsyms_on_each_symbol();
test_perf_kallsyms_on_each_match_symbol();
+ test_perf_kallsyms_lookup_name();
pr_info("finish\n");
return 0;
--
2.39.5
next prev parent reply other threads:[~2026-11-11 11:59 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 11:58 [PATCH v3 next 00/13] kallsyms: optimise symbol search by name David Laight
2026-11-11 11:58 ` [PATCH v3 next 01/13] scripts/kallsyms: Avoid overrunning on-stack buffer David Laight
2026-11-11 11:59 ` [PATCH v3 next 02/13] scripts/kallsyms: Improve error reporting David Laight
2026-11-11 12:14 ` sashiko-bot
2026-11-11 23:33 ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 03/13] scripts/elf-parse: add elf_map_big_endian() helper David Laight
2026-11-11 11:59 ` [PATCH v3 next 04/13] scripts/kallsyms: make use of binary data output optional David Laight
2026-11-11 12:32 ` sashiko-bot
2026-11-11 23:34 ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 05/13] kallsyms: Fix selftest startup delay David Laight
2026-11-11 12:36 ` sashiko-bot
2026-11-11 11:59 ` David Laight [this message]
2026-11-11 23:17 ` [PATCH v3 next 06/13] kallsyms: Improve selftest test_perf_kallsyms_lookup_name() output bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 07/13] kallsyms: Match compressed tokens on the fly during binary search David Laight
2026-11-11 12:46 ` sashiko-bot
2026-11-11 11:59 ` [PATCH v3 next 08/13] kallsyms: Optimise symbol name search David Laight
2026-11-11 12:59 ` sashiko-bot
2026-11-11 11:59 ` [PATCH v3 next 09/13] kallsyms: Add a kernel parameter to change the kallsyms_markers[] density David Laight
2026-11-11 13:07 ` sashiko-bot
2026-11-11 23:33 ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 10/13] scripts/kallsyms: Keep full expansion of tokens David Laight
2026-11-11 11:59 ` [PATCH v3 next 11/13] scripts/kallsyms: Optimise compress_symbols() David Laight
2026-11-11 11:59 ` [PATCH v3 next 12/13] scripts/kallsyms: Reuse tokens that have no references David Laight
2026-11-11 23:34 ` bot+bpf-ci
2026-11-11 11:59 ` [PATCH v3 next 13/13] scripts/kallsyms: Reuse little-used compression tokens David Laight
2026-11-11 13:37 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261111115911.1142000-7-david.laight.linux@gmail.com \
--to=david.laight.linux@gmail.com \
--cc=andrey.grodzovsky@crowdstrike.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=jim.cromie@gmail.com \
--cc=kees@kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=mcgrof@kernel.org \
--cc=pmladek@suse.com \
--cc=rostedt@goodmis.org \
--cc=wusamuel@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.