Add a benchmark to compare performance of 1) uprobe; 2) user program w/o args; 3) user program w/ args; 4) user program w/ args on random cpu. Sample output: ./test_progs -t uprobe_vs_user_prog -v test_uprobe_vs_user_prog:PASS:uprobe_vs_user_prog__open_and_load 0 nsec test_uprobe_vs_user_prog:PASS:get_base_addr 0 nsec test_uprobe_vs_user_prog:PASS:attach_uprobe 0 nsec run_perf_test:PASS:uprobe 0 nsec Each uprobe uses 1419 nanoseconds run_perf_test:PASS:user_prog_no_args 0 nsec Each user_prog_no_args uses 313 nanoseconds run_perf_test:PASS:user_prog_with_args 0 nsec Each user_prog_with_args uses 335 nanoseconds run_perf_test:PASS:user_prog_with_args_on_cpu 0 nsec Each user_prog_with_args_on_cpu uses 2821 nanoseconds Summary: 1/0 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Song Liu <songliubraving@xxxxxx> --- .../bpf/prog_tests/uprobe_vs_user_prog.c | 101 ++++++++++++++++++ .../selftests/bpf/progs/uprobe_vs_user_prog.c | 21 ++++ 2 files changed, 122 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/uprobe_vs_user_prog.c create mode 100644 tools/testing/selftests/bpf/progs/uprobe_vs_user_prog.c diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_vs_user_prog.c b/tools/testing/selftests/bpf/prog_tests/uprobe_vs_user_prog.c new file mode 100644 index 0000000000000..dadd7b56e69ec --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_vs_user_prog.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <test_progs.h> +#include "uprobe_vs_user_prog.skel.h" + +#define REPEAT_CNT 10000ULL + +static int duration; + +static noinline void uprobe_target(void) +{ + asm (""); +} + +struct bpf_prog_test_run_attr attr; + +static void call_user_prog(void) +{ + bpf_prog_test_run_xattr(&attr); +} + +static int numcpu; + +static void call_user_prog_on_cpu(void) +{ + static int cpu = 0; + + attr.cpu_plus = cpu + 1; + bpf_prog_test_run_xattr(&attr); + cpu = (cpu + 1) % numcpu; +} + +typedef void (__run_func)(void); + +static void run_perf_test(struct uprobe_vs_user_prog *skel, + __run_func func, const char *name) +{ + __u64 start_time, total_time; + int i; + + skel->bss->sum = 0; + + start_time = time_get_ns(); + for (i = 0; i < REPEAT_CNT; i++) + func(); + total_time = time_get_ns() - start_time; + + CHECK(skel->bss->sum != REPEAT_CNT, name, + "missed %llu times\n", REPEAT_CNT - skel->bss->sum); + printf("Each %s uses %llu nanoseconds\n", name, total_time / REPEAT_CNT); +} + +void test_uprobe_vs_user_prog(void) +{ + struct bpf_user_prog_args args = {}; + struct uprobe_vs_user_prog *skel; + struct bpf_link *uprobe_link; + size_t uprobe_offset; + ssize_t base_addr; + + skel = uprobe_vs_user_prog__open_and_load(); + + if (CHECK(!skel, "uprobe_vs_user_prog__open_and_load", + "skeleton open_and_laod failed\n")) + return; + + base_addr = get_base_addr(); + if (CHECK(base_addr < 0, "get_base_addr", + "failed to find base addr: %zd", base_addr)) + return; + uprobe_offset = (size_t)&uprobe_target - base_addr; + uprobe_link = bpf_program__attach_uprobe(skel->progs.handle_uprobe, + false /* retprobe */, + 0 /* self pid */, + "/proc/self/exe", + uprobe_offset); + + if (CHECK(IS_ERR(uprobe_link), "attach_uprobe", + "err %ld\n", PTR_ERR(uprobe_link))) + goto cleanup; + skel->links.handle_uprobe = uprobe_link; + + run_perf_test(skel, uprobe_target, "uprobe"); + + attr.prog_fd = bpf_program__fd(skel->progs.user_prog); + run_perf_test(skel, call_user_prog, "user_prog_no_args"); + + attr.data_size_in = sizeof(args); + attr.data_in = &args; + run_perf_test(skel, call_user_prog, "user_prog_with_args"); + + numcpu = libbpf_num_possible_cpus(); + + if (numcpu <= 0) + goto cleanup; + + run_perf_test(skel, call_user_prog_on_cpu, + "user_prog_with_args_on_cpu"); + +cleanup: + uprobe_vs_user_prog__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/uprobe_vs_user_prog.c b/tools/testing/selftests/bpf/progs/uprobe_vs_user_prog.c new file mode 100644 index 0000000000000..8b327b7cee30d --- /dev/null +++ b/tools/testing/selftests/bpf/progs/uprobe_vs_user_prog.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017 Facebook +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +volatile __u64 sum = 0; + +SEC("uprobe/func") +int handle_uprobe(struct pt_regs *ctx) +{ + sum++; + return 0; +} + +SEC("user") +int user_prog(struct pt_regs *ctx) +{ + sum++; + return 0; +} -- 2.24.1