[PATCH 5/5] perf bench uprobe trace_printk: Add entry attaching an BPF program that does a trace_printk

From: Arnaldo Carvalho de Melo
Date: Wed Jul 19 2023 - 16:50:03 EST


From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>

[root@five ~]# perf bench uprobe all
# Running uprobe/baseline benchmark...
# Executed 1,000 usleep(1000) calls
Total time: 1,053,963 usecs

1,053.963 usecs/op

# Running uprobe/empty benchmark...
# Executed 1,000 usleep(1000) calls
Total time: 1,056,293 usecs +2,330 to baseline

1,056.293 usecs/op 2.330 usecs/op to baseline

# Running uprobe/trace_printk benchmark...
# Executed 1,000 usleep(1000) calls
Total time: 1,056,977 usecs +3,014 to baseline +684 to previous

1,056.977 usecs/op 3.014 usecs/op to baseline 0.684 usecs/op to previous

[root@five ~]#

Cc: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Cc: Andre Fredette <anfredet@xxxxxxxxxx>
Cc: Clark Williams <williams@xxxxxxxxxx>
Cc: Dave Tucker <datucker@xxxxxxxxxx>
Cc: Derek Barbosa <debarbos@xxxxxxxxxx>
Cc: Ian Rogers <irogers@xxxxxxxxxx>
Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Cc: Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx>
Cc: Namhyung Kim <namhyung@xxxxxxxxxx>
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
---
tools/perf/bench/bench.h | 1 +
tools/perf/bench/uprobe.c | 39 +++++++++++++++------
tools/perf/builtin-bench.c | 1 +
tools/perf/util/bpf_skel/bench_uprobe.bpf.c | 11 ++++++
4 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index daf4850b441cf91c..50de4773651f9914 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -44,6 +44,7 @@ int bench_breakpoint_thread(int argc, const char **argv);
int bench_breakpoint_enable(int argc, const char **argv);
int bench_uprobe_baseline(int argc, const char **argv);
int bench_uprobe_empty(int argc, const char **argv);
+int bench_uprobe_trace_printk(int argc, const char **argv);
int bench_pmu_scan(int argc, const char **argv);

#define BENCH_FORMAT_DEFAULT_STR "default"
diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c
index dfb90038a4f7a06a..914c0817fe8ad31b 100644
--- a/tools/perf/bench/uprobe.c
+++ b/tools/perf/bench/uprobe.c
@@ -11,6 +11,7 @@
#include <subcmd/parse-options.h>
#include "../builtin.h"
#include "bench.h"
+#include <linux/compiler.h>
#include <linux/time64.h>

#include <inttypes.h>
@@ -27,6 +28,7 @@ static int loops = LOOPS_DEFAULT;
enum bench_uprobe {
BENCH_UPROBE__BASELINE,
BENCH_UPROBE__EMPTY,
+ BENCH_UPROBE__TRACE_PRINTK,
};

static const struct option options[] = {
@@ -42,9 +44,21 @@ static const char * const bench_uprobe_usage[] = {
#ifdef HAVE_BPF_SKEL
#include "bpf_skel/bench_uprobe.skel.h"

+#define bench_uprobe__attach_uprobe(prog) \
+ skel->links.prog = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.prog, \
+ /*pid=*/-1, \
+ /*binary_path=*/"/lib64/libc.so.6", \
+ /*func_offset=*/0, \
+ /*opts=*/&uprobe_opts); \
+ if (!skel->links.prog) { \
+ err = -errno; \
+ fprintf(stderr, "Failed to attach bench uprobe \"%s\": %s\n", #prog, strerror(errno)); \
+ goto cleanup; \
+ }
+
struct bench_uprobe_bpf *skel;

-static int bench_uprobe__setup_bpf_skel(void)
+static int bench_uprobe__setup_bpf_skel(enum bench_uprobe bench)
{
DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
int err;
@@ -63,14 +77,12 @@ static int bench_uprobe__setup_bpf_skel(void)
}

uprobe_opts.func_name = "usleep";
- skel->links.empty = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.empty,
- /*pid=*/-1,
- /*binary_path=*/"/lib64/libc.so.6",
- /*func_offset=*/0,
- /*opts=*/&uprobe_opts);
- if (!skel->links.empty) {
- err = -errno;
- fprintf(stderr, "Failed to attach bench uprobe: %s\n", strerror(errno));
+ switch (bench) {
+ case BENCH_UPROBE__BASELINE: break;
+ case BENCH_UPROBE__EMPTY: bench_uprobe__attach_uprobe(empty); break;
+ case BENCH_UPROBE__TRACE_PRINTK: bench_uprobe__attach_uprobe(trace_printk); break;
+ default:
+ fprintf(stderr, "Invalid bench: %d\n", bench);
goto cleanup;
}

@@ -88,7 +100,7 @@ static void bench_uprobe__teardown_bpf_skel(void)
}
}
#else
-static int bench_uprobe__setup_bpf_skel(void) { return 0; }
+static int bench_uprobe__setup_bpf_skel(enum bench_uprobe bench __maybe_unused) { return 0; }
static void bench_uprobe__teardown_bpf_skel(void) {};
#endif

@@ -135,7 +147,7 @@ static int bench_uprobe(int argc, const char **argv, enum bench_uprobe bench)

argc = parse_options(argc, argv, options, bench_uprobe_usage, 0);

- if (bench != BENCH_UPROBE__BASELINE && bench_uprobe__setup_bpf_skel() < 0)
+ if (bench != BENCH_UPROBE__BASELINE && bench_uprobe__setup_bpf_skel(bench) < 0)
return 0;

clock_gettime(CLOCK_REALTIME, &start);
@@ -179,3 +191,8 @@ int bench_uprobe_empty(int argc, const char **argv)
{
return bench_uprobe(argc, argv, BENCH_UPROBE__EMPTY);
}
+
+int bench_uprobe_trace_printk(int argc, const char **argv)
+{
+ return bench_uprobe(argc, argv, BENCH_UPROBE__TRACE_PRINTK);
+}
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 1021680bbc6d4298..f60ccafccac25602 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -107,6 +107,7 @@ static struct bench breakpoint_benchmarks[] = {
static struct bench uprobe_benchmarks[] = {
{ "baseline", "Baseline libc usleep(1000) call", bench_uprobe_baseline, },
{ "empty", "Attach empty BPF prog to uprobe on usleep, system wide", bench_uprobe_empty, },
+ { "trace_printk", "Attach trace_printk BPF prog to uprobe on usleep syswide", bench_uprobe_trace_printk, },
{ NULL, NULL, NULL },
};

diff --git a/tools/perf/util/bpf_skel/bench_uprobe.bpf.c b/tools/perf/util/bpf_skel/bench_uprobe.bpf.c
index 1365dcc5dddff546..7046bea5da871627 100644
--- a/tools/perf/util/bpf_skel/bench_uprobe.bpf.c
+++ b/tools/perf/util/bpf_skel/bench_uprobe.bpf.c
@@ -3,10 +3,21 @@
#include "vmlinux.h"
#include <bpf/bpf_tracing.h>

+unsigned int nr_uprobes;
+
SEC("uprobe")
int BPF_UPROBE(empty)
{
return 0;
}

+SEC("uprobe")
+int BPF_UPROBE(trace_printk)
+{
+ char fmt[] = "perf bench uprobe %u";
+
+ bpf_trace_printk(fmt, sizeof(fmt), ++nr_uprobes);
+ return 0;
+}
+
char LICENSE[] SEC("license") = "Dual BSD/GPL";
--
2.41.0