In CI, the tracing_multi_bench_attach test could cost >10s, which should be avoided in daily CI running.
./test_progs -t tracing_multi_bench_attach -v WATCHDOG: test case tracing_multi_bench_attach executes for 10 seconds... serial_test_tracing_multi_bench_attach: found 40163 functions serial_test_tracing_multi_bench_attach: attached in 9.367s serial_test_tracing_multi_bench_attach: detached in 1.798s #546 tracing_multi_bench_attach:OK Since it is for benchmark attachment of tracing_multi link, move it to the generic bench framework. ./bench tracing-multi-attach Setting up benchmark 'tracing-multi-attach'... tracing-multi-attach: found 40166 functions tracing-multi-attach: attached in 9.278s tracing-multi-attach: detached in 1.836s Assisted-by: Codex:gpt-5.6-sol Signed-off-by: Leon Hwang <[email protected]> --- tools/testing/selftests/bpf/Makefile | 2 + tools/testing/selftests/bpf/bench.c | 2 + .../bpf/benchs/bench_tracing_multi_attach.c | 177 ++++++++++++++++++ .../selftests/bpf/prog_tests/tracing_multi.c | 125 ------------- 4 files changed, 181 insertions(+), 125 deletions(-) create mode 100644 tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 55d394438705..e4d8cbd51d71 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -966,6 +966,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \ $(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h $(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h $(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h +$(OUTPUT)/bench_tracing_multi_attach.o: $(OUTPUT)/tracing_multi_bench.skel.h $(OUTPUT)/bench_bpf_hashmap_full_update.o: $(OUTPUT)/bpf_hashmap_full_update_bench.skel.h $(OUTPUT)/bench_local_storage.o: $(OUTPUT)/local_storage_bench.skel.h $(OUTPUT)/bench_local_storage_rcu_tasks_trace.o: $(OUTPUT)/local_storage_rcu_tasks_trace_bench.skel.h @@ -991,6 +992,7 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \ $(OUTPUT)/bench_bloom_filter_map.o \ $(OUTPUT)/bench_bpf_loop.o \ $(OUTPUT)/bench_strncmp.o \ + $(OUTPUT)/bench_tracing_multi_attach.o \ $(OUTPUT)/bench_bpf_hashmap_full_update.o \ $(OUTPUT)/bench_local_storage.o \ $(OUTPUT)/bench_local_storage_rcu_tasks_trace.o \ diff --git a/tools/testing/selftests/bpf/bench.c b/tools/testing/selftests/bpf/bench.c index 3d9d2cd7764b..5ce31459835c 100644 --- a/tools/testing/selftests/bpf/bench.c +++ b/tools/testing/selftests/bpf/bench.c @@ -545,6 +545,7 @@ extern const struct bench bench_trig_uprobe_multi_nop5; extern const struct bench bench_trig_uretprobe_multi_nop5; extern const struct bench bench_trig_usdt_nop; extern const struct bench bench_trig_usdt_nop5; +extern const struct bench bench_tracing_multi_attach; #endif extern const struct bench bench_rb_libbpf; @@ -628,6 +629,7 @@ static const struct bench *benchs[] = { &bench_trig_uretprobe_multi_nop5, &bench_trig_usdt_nop, &bench_trig_usdt_nop5, + &bench_tracing_multi_attach, #endif /* ringbuf/perfbuf benchmarks */ &bench_rb_libbpf, diff --git a/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c b/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c new file mode 100644 index 000000000000..7389d1742ddc --- /dev/null +++ b/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include <search.h> +#include <stdio.h> +#include <string.h> +#include <bpf/btf.h> +#include "bench.h" +#include "testing_helpers.h" +#include "trace_helpers.h" +#include "tracing_multi_bench.skel.h" +#include "bpf/libbpf_internal.h" + +static int compare(const void *ppa, const void *ppb) +{ + const char *pa = *(const char **)ppa; + const char *pb = *(const char **)ppb; + + return strcmp(pa, pb); +} + +static void tdestroy_free_nop(void *ptr) +{ +} + +static void tracing_multi_attach_setup(void) +{ + LIBBPF_OPTS(bpf_tracing_multi_opts, opts); + struct tracing_multi_bench *skel = NULL; + long attach_start_ns, attach_end_ns; + long detach_start_ns, detach_end_ns; + double attach_delta, detach_delta; + struct bpf_link *link = NULL; + size_t i, cap = 0, cnt = 0; + struct ksyms *ksyms = NULL; + void *root = NULL; + void *dups = NULL; + __u32 *ids = NULL; + __u32 nr, type_id; + struct btf *btf; + int err; + + setup_libbpf(); + + btf = btf__load_vmlinux_btf(); + err = libbpf_get_error(btf); + if (err) { + btf = NULL; + fprintf(stderr, "failed to load vmlinux BTF: %s\n", strerror(-err)); + goto cleanup; + } + + skel = tracing_multi_bench__open_and_load(); + err = libbpf_get_error(skel); + if (!skel) { + fprintf(stderr, "failed to open and load skeleton: %s\n", strerror(-err)); + goto cleanup; + } + + err = bpf_get_ksyms(&ksyms, true); + if (err) { + fprintf(stderr, "failed to get kernel symbols: %s\n", strerror(-err)); + goto cleanup; + } + + /* Get all ftrace 'safe' symbols.. */ + for (i = 0; i < ksyms->filtered_cnt; i++) { + if (!tsearch(&ksyms->filtered_syms[i], &root, compare)) { + err = -ENOMEM; + fprintf(stderr, "failed to index ftrace symbols\n"); + goto cleanup; + } + } + + /* + * Collect names that are not unique in kallsyms. The kernel resolves a + * tracing-multi BTF id to an address with kallsyms_lookup_name(), which + * returns the first symbol of that name. For a duplicate name that may + * be a different (non-ftrace-able) instance than the ftrace-able one in + * available_filter_functions, so attaching to it by BTF id fails with + * -ENOENT (e.g. t_start/t_next/t_stop). ksyms->syms is sorted by name, + * so equal names are adjacent. + */ + for (i = 1; i < ksyms->sym_cnt; i++) { + if (strcmp(ksyms->syms[i].name, ksyms->syms[i - 1].name)) + continue; + if (!tsearch(&ksyms->syms[i].name, &dups, compare)) { + err = -ENOMEM; + fprintf(stderr, "failed to index duplicate kernel symbols\n"); + goto cleanup; + } + } + + /* ..and filter them through BTF and btf_type_is_traceable_func. */ + nr = btf__type_cnt(btf); + for (type_id = 1; type_id < nr; type_id++) { + const struct btf_type *type; + const char *str; + + type = btf__type_by_id(btf, type_id); + if (!type) + break; + + if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) + continue; + + str = btf__name_by_offset(btf, type->name_off); + if (!str) + break; + + if (!tfind(&str, &root, compare)) + continue; + + /* Skip names that are not unique in kallsyms, see above. */ + if (tfind(&str, &dups, compare)) + continue; + + if (!btf_type_is_traceable_func(btf, type)) + continue; + + err = libbpf_ensure_mem((void **)&ids, &cap, sizeof(*ids), cnt + 1); + if (err) { + fprintf(stderr, "failed to allocate BTF ID array: %s\n", + strerror(-err)); + goto cleanup; + } + + ids[cnt++] = type_id; + } + + opts.ids = ids; + opts.cnt = cnt; + + attach_start_ns = get_time_ns(); + link = bpf_program__attach_tracing_multi(skel->progs.bench, NULL, &opts); + attach_end_ns = get_time_ns(); + + err = libbpf_get_error(link); + if (err) { + link = NULL; + fprintf(stderr, "failed to attach tracing multi link: %s\n", + strerror(-err)); + goto cleanup; + } + + detach_start_ns = get_time_ns(); + err = bpf_link__destroy(link); + detach_end_ns = get_time_ns(); + link = NULL; + if (err) { + fprintf(stderr, "failed to detach tracing multi link: %s\n", + strerror(-err)); + goto cleanup; + } + + attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0; + detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0; + + printf("%s: found %zu functions\n", bench->name, cnt); + printf("%s: attached in %7.3lfs\n", bench->name, attach_delta); + printf("%s: detached in %7.3lfs\n", bench->name, detach_delta); + +cleanup: + bpf_link__destroy(link); + tracing_multi_bench__destroy(skel); + tdestroy(root, tdestroy_free_nop); + tdestroy(dups, tdestroy_free_nop); + free_kallsyms_local(ksyms); + free(ids); + btf__free(btf); + + exit(err ? 1 : 0); +} + +const struct bench bench_tracing_multi_attach = { + .name = "tracing-multi-attach", + .setup = tracing_multi_attach_setup, +}; diff --git a/tools/testing/selftests/bpf/prog_tests/tracing_multi.c b/tools/testing/selftests/bpf/prog_tests/tracing_multi.c index 0aa9532a05cf..fd4f256d2e0a 100644 --- a/tools/testing/selftests/bpf/prog_tests/tracing_multi.c +++ b/tools/testing/selftests/bpf/prog_tests/tracing_multi.c @@ -3,14 +3,12 @@ #include <test_progs.h> #include <bpf/btf.h> #include <search.h> -#include "bpf/libbpf_internal.h" #include "tracing_multi.skel.h" #include "tracing_multi_module.skel.h" #include "tracing_multi_intersect.skel.h" #include "tracing_multi_session.skel.h" #include "tracing_multi_fail.skel.h" #include "tracing_multi_verifier.skel.h" -#include "tracing_multi_bench.skel.h" #include "tracing_multi_rollback.skel.h" #include "trace_helpers.h" @@ -662,129 +660,6 @@ static void test_attach_api_fails(void) free(ids2); } -void serial_test_tracing_multi_bench_attach(void) -{ - LIBBPF_OPTS(bpf_tracing_multi_opts, opts); - struct tracing_multi_bench *skel = NULL; - long attach_start_ns, attach_end_ns; - long detach_start_ns, detach_end_ns; - double attach_delta, detach_delta; - struct bpf_link *link = NULL; - size_t i, cap = 0, cnt = 0; - struct ksyms *ksyms = NULL; - void *root = NULL; - void *dups = NULL; - __u32 *ids = NULL; - __u32 nr, type_id; - struct btf *btf; - int err; - -#ifndef __x86_64__ - test__skip(); - return; -#endif - - btf = btf__load_vmlinux_btf(); - if (!ASSERT_OK_PTR(btf, "btf__load_vmlinux_btf")) - return; - - skel = tracing_multi_bench__open_and_load(); - if (!ASSERT_OK_PTR(skel, "tracing_multi_bench__open_and_load")) - goto cleanup; - - if (!ASSERT_OK(bpf_get_ksyms(&ksyms, true), "get_syms")) - goto cleanup; - - /* Get all ftrace 'safe' symbols.. */ - for (i = 0; i < ksyms->filtered_cnt; i++) { - if (!tsearch(&ksyms->filtered_syms[i], &root, compare)) { - ASSERT_FAIL("tsearch failed"); - goto cleanup; - } - } - - /* - * Collect names that are not unique in kallsyms. The kernel resolves a - * tracing-multi BTF id to an address with kallsyms_lookup_name(), which - * returns the first symbol of that name. For a duplicate name that may - * be a different (non-ftrace-able) instance than the ftrace-able one in - * available_filter_functions, so attaching to it by BTF id fails with - * -ENOENT (e.g. t_start/t_next/t_stop). ksyms->syms is sorted by name, - * so equal names are adjacent. - */ - for (i = 1; i < ksyms->sym_cnt; i++) { - if (strcmp(ksyms->syms[i].name, ksyms->syms[i - 1].name)) - continue; - if (!tsearch(&ksyms->syms[i].name, &dups, compare)) { - ASSERT_FAIL("tsearch failed"); - goto cleanup; - } - } - - /* ..and filter them through BTF and btf_type_is_traceable_func. */ - nr = btf__type_cnt(btf); - for (type_id = 1; type_id < nr; type_id++) { - const struct btf_type *type; - const char *str; - - type = btf__type_by_id(btf, type_id); - if (!type) - break; - - if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) - continue; - - str = btf__name_by_offset(btf, type->name_off); - if (!str) - break; - - if (!tfind(&str, &root, compare)) - continue; - - /* Skip names that are not unique in kallsyms, see above. */ - if (tfind(&str, &dups, compare)) - continue; - - if (!btf_type_is_traceable_func(btf, type)) - continue; - - err = libbpf_ensure_mem((void **) &ids, &cap, sizeof(*ids), cnt + 1); - if (err) - goto cleanup; - - ids[cnt++] = type_id; - } - - opts.ids = ids; - opts.cnt = cnt; - - attach_start_ns = get_time_ns(); - link = bpf_program__attach_tracing_multi(skel->progs.bench, NULL, &opts); - attach_end_ns = get_time_ns(); - - if (!ASSERT_OK_PTR(link, "bpf_program__attach_tracing_multi")) - goto cleanup; - - detach_start_ns = get_time_ns(); - bpf_link__destroy(link); - detach_end_ns = get_time_ns(); - - attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0; - detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0; - - printf("%s: found %lu functions\n", __func__, cnt); - printf("%s: attached in %7.3lfs\n", __func__, attach_delta); - printf("%s: detached in %7.3lfs\n", __func__, detach_delta); - -cleanup: - tracing_multi_bench__destroy(skel); - tdestroy(root, tdestroy_free_nop); - tdestroy(dups, tdestroy_free_nop); - free_kallsyms_local(ksyms); - free(ids); - btf__free(btf); -} - static void tracing_multi_rollback_run(struct tracing_multi_rollback *skel) { LIBBPF_OPTS(bpf_test_run_opts, topts); -- 2.55.0

