diff mbox series

[bpf-next,2/3] selftest/bpf: fmod_ret prog and implement test_overhead as part of bench

Message ID 20200508070548.2358701-3-andriin@fb.com
State Changes Requested
Delegated to: BPF Maintainers
Headers show
Series Add benchmark runner and few benchmarks | expand

Commit Message

Andrii Nakryiko May 8, 2020, 7:05 a.m. UTC
Add fmod_ret BPF program to existing test_overhead selftest. Also re-implement
user-space benchmarking part into benchmark runner to compare results.  Results
with ./bench are consistently somewhat lower than test_overhead's, but relative
performance of various types of BPF programs stay consisten (e.g., kretprobe is
noticeably slower).

To test with ./bench, the following command was used:

for i in base kprobe kretprobe rawtp fentry fexit fmodret; \
do \
    summary=$(sudo ./bench -w2 -d5 -a rename-$i | \
              tail -n1 | cut -d'(' -f1 | cut -d' ' -f3-) && \
    printf "%-10s: %s\n" $i "$summary"; \
done

This gives the following numbers:

  base      :    3.975 ± 0.065M/s
  kprobe    :    3.268 ± 0.095M/s
  kretprobe :    2.496 ± 0.040M/s
  rawtp     :    3.899 ± 0.078M/s
  fentry    :    3.836 ± 0.049M/s
  fexit     :    3.660 ± 0.082M/s
  fmodret   :    3.776 ± 0.033M/s

While running test_overhead gives:

  task_rename base        4457K events per sec
  task_rename kprobe      3849K events per sec
  task_rename kretprobe   2729K events per sec
  task_rename raw_tp      4506K events per sec
  task_rename fentry      4381K events per sec
  task_rename fexit       4349K events per sec
  task_rename fmod_ret    4130K events per sec

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
---
 tools/testing/selftests/bpf/Makefile          |   4 +-
 tools/testing/selftests/bpf/bench.c           |  14 ++
 tools/testing/selftests/bpf/bench_rename.c    | 195 ++++++++++++++++++
 .../selftests/bpf/prog_tests/test_overhead.c  |  14 +-
 .../selftests/bpf/progs/test_overhead.c       |   6 +
 5 files changed, 231 insertions(+), 2 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/bench_rename.c

Comments

John Fastabend May 8, 2020, 3:57 p.m. UTC | #1
Andrii Nakryiko wrote:
> Add fmod_ret BPF program to existing test_overhead selftest. Also re-implement
> user-space benchmarking part into benchmark runner to compare results.  Results
> with ./bench are consistently somewhat lower than test_overhead's, but relative
> performance of various types of BPF programs stay consisten (e.g., kretprobe is
> noticeably slower).
> 
> To test with ./bench, the following command was used:
> 
> for i in base kprobe kretprobe rawtp fentry fexit fmodret; \
> do \
>     summary=$(sudo ./bench -w2 -d5 -a rename-$i | \
>               tail -n1 | cut -d'(' -f1 | cut -d' ' -f3-) && \
>     printf "%-10s: %s\n" $i "$summary"; \
> done

might be nice to have a script ./bench_tracing_overhead.sh when its in its
own directory ./bench. Otherwise I'll have to look this up every single
time I'm sure.

> 
> This gives the following numbers:
> 
>   base      :    3.975 ± 0.065M/s
>   kprobe    :    3.268 ± 0.095M/s
>   kretprobe :    2.496 ± 0.040M/s
>   rawtp     :    3.899 ± 0.078M/s
>   fentry    :    3.836 ± 0.049M/s
>   fexit     :    3.660 ± 0.082M/s
>   fmodret   :    3.776 ± 0.033M/s
> 
> While running test_overhead gives:
> 
>   task_rename base        4457K events per sec
>   task_rename kprobe      3849K events per sec
>   task_rename kretprobe   2729K events per sec
>   task_rename raw_tp      4506K events per sec
>   task_rename fentry      4381K events per sec
>   task_rename fexit       4349K events per sec
>   task_rename fmod_ret    4130K events per sec
> 
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> ---

LGTM

Acked-by: John Fastabend <john.fastabend@gmail.com>
Andrii Nakryiko May 8, 2020, 6:01 p.m. UTC | #2
On Fri, May 8, 2020 at 8:57 AM John Fastabend <john.fastabend@gmail.com> wrote:
>
> Andrii Nakryiko wrote:
> > Add fmod_ret BPF program to existing test_overhead selftest. Also re-implement
> > user-space benchmarking part into benchmark runner to compare results.  Results
> > with ./bench are consistently somewhat lower than test_overhead's, but relative
> > performance of various types of BPF programs stay consisten (e.g., kretprobe is
> > noticeably slower).
> >
> > To test with ./bench, the following command was used:
> >
> > for i in base kprobe kretprobe rawtp fentry fexit fmodret; \
> > do \
> >     summary=$(sudo ./bench -w2 -d5 -a rename-$i | \
> >               tail -n1 | cut -d'(' -f1 | cut -d' ' -f3-) && \
> >     printf "%-10s: %s\n" $i "$summary"; \
> > done
>
> might be nice to have a script ./bench_tracing_overhead.sh when its in its
> own directory ./bench. Otherwise I'll have to look this up every single
> time I'm sure.

Yeah, I didn't want to pollute selftests/bpf directory, but with a
separate subdir it makes more sense. I'll put it there. For ringbuf
I'll have much longer scripts, so having them in file is a necessity.

>
> >
> > This gives the following numbers:
> >
> >   base      :    3.975 ± 0.065M/s
> >   kprobe    :    3.268 ± 0.095M/s
> >   kretprobe :    2.496 ± 0.040M/s
> >   rawtp     :    3.899 ± 0.078M/s
> >   fentry    :    3.836 ± 0.049M/s
> >   fexit     :    3.660 ± 0.082M/s
> >   fmodret   :    3.776 ± 0.033M/s
> >
> > While running test_overhead gives:
> >
> >   task_rename base        4457K events per sec
> >   task_rename kprobe      3849K events per sec
> >   task_rename kretprobe   2729K events per sec
> >   task_rename raw_tp      4506K events per sec
> >   task_rename fentry      4381K events per sec
> >   task_rename fexit       4349K events per sec
> >   task_rename fmod_ret    4130K events per sec
> >
> > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> > ---
>
> LGTM
>
> Acked-by: John Fastabend <john.fastabend@gmail.com>
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index ab03362d46e4..275c5873a75f 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -408,9 +408,11 @@  $(OUTPUT)/test_cpp: test_cpp.cpp $(OUTPUT)/test_core_extern.skel.h $(BPFOBJ)
 # Benchmark runner
 $(OUTPUT)/bench.o:          bench.h
 $(OUTPUT)/bench_count.o:    bench.h
+$(OUTPUT)/bench_rename.o:   bench.h $(OUTPUT)/test_overhead.skel.h
 $(OUTPUT)/bench: LDLIBS += -lm
 $(OUTPUT)/bench: $(OUTPUT)/bench.o \
-		 $(OUTPUT)/bench_count.o
+		 $(OUTPUT)/bench_count.o \
+		 $(OUTPUT)/bench_rename.o
 	$(call msg,BINARY,,$@)
 	$(CC) $(LDFLAGS) -o $@ $(filter %.a %.o,$^) $(LDLIBS)
 
diff --git a/tools/testing/selftests/bpf/bench.c b/tools/testing/selftests/bpf/bench.c
index a20482bb74e2..6ce4002612c8 100644
--- a/tools/testing/selftests/bpf/bench.c
+++ b/tools/testing/selftests/bpf/bench.c
@@ -246,10 +246,24 @@  const struct bench *bench = NULL;
 
 extern const struct bench bench_count_global;
 extern const struct bench bench_count_local;
+extern const struct bench bench_rename_base;
+extern const struct bench bench_rename_kprobe;
+extern const struct bench bench_rename_kretprobe;
+extern const struct bench bench_rename_rawtp;
+extern const struct bench bench_rename_fentry;
+extern const struct bench bench_rename_fexit;
+extern const struct bench bench_rename_fmodret;
 
 static const struct bench *benchs[] = {
 	&bench_count_global,
 	&bench_count_local,
+	&bench_rename_base,
+	&bench_rename_kprobe,
+	&bench_rename_kretprobe,
+	&bench_rename_rawtp,
+	&bench_rename_fentry,
+	&bench_rename_fexit,
+	&bench_rename_fmodret,
 };
 
 static void setup_benchmark()
diff --git a/tools/testing/selftests/bpf/bench_rename.c b/tools/testing/selftests/bpf/bench_rename.c
new file mode 100644
index 000000000000..e74cff40f4fe
--- /dev/null
+++ b/tools/testing/selftests/bpf/bench_rename.c
@@ -0,0 +1,195 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2020 Facebook */
+#include <fcntl.h>
+#include "bench.h"
+#include "test_overhead.skel.h"
+
+/* BPF triggering benchmarks */
+static struct ctx {
+	struct test_overhead *skel;
+	struct counter hits;
+	int fd;
+} ctx;
+
+static void validate()
+{
+	if (env.producer_cnt != 1) {
+		fprintf(stderr, "benchmark doesn't support multi-producer!\n");
+		exit(1);
+	}
+	if (env.consumer_cnt != 1) {
+		fprintf(stderr, "benchmark doesn't support multi-consumer!\n");
+		exit(1);
+	}
+}
+
+static void *producer(void *input)
+{
+	char buf[] = "test_overhead";
+	int err;
+
+	while (true) {
+		err = write(ctx.fd, buf, sizeof(buf));
+		if (err < 0) {
+			fprintf(stderr, "write failed\n");
+			exit(1);
+		}
+		atomic_inc(&ctx.hits.value);
+	}
+}
+
+static void measure(struct bench_res *res)
+{
+	res->hits = atomic_swap(&ctx.hits.value, 0);
+}
+
+static void setup_ctx()
+{
+	setup_libbpf();
+
+	ctx.skel = test_overhead__open_and_load();
+	if (!ctx.skel) {
+		fprintf(stderr, "failed to open skeleton\n");
+		exit(1);
+	}
+
+	ctx.fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);
+	if (ctx.fd < 0) {
+		fprintf(stderr, "failed to open /proc/self/comm: %d\n", -errno);
+		exit(1);
+	}
+}
+
+static void attach_bpf(struct bpf_program *prog)
+{
+	struct bpf_link *link;
+
+	link = bpf_program__attach(prog);
+	if (IS_ERR(link)) {
+		fprintf(stderr, "failed to attach program!\n");
+		exit(1);
+	}
+}
+
+static void setup_base()
+{
+	setup_ctx();
+}
+
+static void setup_kprobe()
+{
+	setup_ctx();
+	attach_bpf(ctx.skel->progs.prog1);
+}
+
+static void setup_kretprobe()
+{
+	setup_ctx();
+	attach_bpf(ctx.skel->progs.prog2);
+}
+
+static void setup_rawtp()
+{
+	setup_ctx();
+	attach_bpf(ctx.skel->progs.prog3);
+}
+
+static void setup_fentry()
+{
+	setup_ctx();
+	attach_bpf(ctx.skel->progs.prog4);
+}
+
+static void setup_fexit()
+{
+	setup_ctx();
+	attach_bpf(ctx.skel->progs.prog5);
+}
+
+static void setup_fmodret()
+{
+	setup_ctx();
+	attach_bpf(ctx.skel->progs.prog6);
+}
+
+static void *consumer(void *input)
+{
+	return NULL;
+}
+
+const struct bench bench_rename_base = {
+	.name = "rename-base",
+	.validate = validate,
+	.setup = setup_base,
+	.producer_thread = producer,
+	.consumer_thread = consumer,
+	.measure = measure,
+	.report_progress = hits_drops_report_progress,
+	.report_final = hits_drops_report_final,
+};
+
+const struct bench bench_rename_kprobe = {
+	.name = "rename-kprobe",
+	.validate = validate,
+	.setup = setup_kprobe,
+	.producer_thread = producer,
+	.consumer_thread = consumer,
+	.measure = measure,
+	.report_progress = hits_drops_report_progress,
+	.report_final = hits_drops_report_final,
+};
+
+const struct bench bench_rename_kretprobe = {
+	.name = "rename-kretprobe",
+	.validate = validate,
+	.setup = setup_kretprobe,
+	.producer_thread = producer,
+	.consumer_thread = consumer,
+	.measure = measure,
+	.report_progress = hits_drops_report_progress,
+	.report_final = hits_drops_report_final,
+};
+
+const struct bench bench_rename_rawtp = {
+	.name = "rename-rawtp",
+	.validate = validate,
+	.setup = setup_rawtp,
+	.producer_thread = producer,
+	.consumer_thread = consumer,
+	.measure = measure,
+	.report_progress = hits_drops_report_progress,
+	.report_final = hits_drops_report_final,
+};
+
+const struct bench bench_rename_fentry = {
+	.name = "rename-fentry",
+	.validate = validate,
+	.setup = setup_fentry,
+	.producer_thread = producer,
+	.consumer_thread = consumer,
+	.measure = measure,
+	.report_progress = hits_drops_report_progress,
+	.report_final = hits_drops_report_final,
+};
+
+const struct bench bench_rename_fexit = {
+	.name = "rename-fexit",
+	.validate = validate,
+	.setup = setup_fexit,
+	.producer_thread = producer,
+	.consumer_thread = consumer,
+	.measure = measure,
+	.report_progress = hits_drops_report_progress,
+	.report_final = hits_drops_report_final,
+};
+
+const struct bench bench_rename_fmodret = {
+	.name = "rename-fmodret",
+	.validate = validate,
+	.setup = setup_fmodret,
+	.producer_thread = producer,
+	.consumer_thread = consumer,
+	.measure = measure,
+	.report_progress = hits_drops_report_progress,
+	.report_final = hits_drops_report_final,
+};
diff --git a/tools/testing/selftests/bpf/prog_tests/test_overhead.c b/tools/testing/selftests/bpf/prog_tests/test_overhead.c
index 465b371a561d..2702df2b2343 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_overhead.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_overhead.c
@@ -61,9 +61,10 @@  void test_test_overhead(void)
 	const char *raw_tp_name = "raw_tp/task_rename";
 	const char *fentry_name = "fentry/__set_task_comm";
 	const char *fexit_name = "fexit/__set_task_comm";
+	const char *fmodret_name = "fmod_ret/__set_task_comm";
 	const char *kprobe_func = "__set_task_comm";
 	struct bpf_program *kprobe_prog, *kretprobe_prog, *raw_tp_prog;
-	struct bpf_program *fentry_prog, *fexit_prog;
+	struct bpf_program *fentry_prog, *fexit_prog, *fmodret_prog;
 	struct bpf_object *obj;
 	struct bpf_link *link;
 	int err, duration = 0;
@@ -96,6 +97,10 @@  void test_test_overhead(void)
 	if (CHECK(!fexit_prog, "find_probe",
 		  "prog '%s' not found\n", fexit_name))
 		goto cleanup;
+	fmodret_prog = bpf_object__find_program_by_title(obj, fmodret_name);
+	if (CHECK(!fmodret_prog, "find_probe",
+		  "prog '%s' not found\n", fmodret_name))
+		goto cleanup;
 
 	err = bpf_object__load(obj);
 	if (CHECK(err, "obj_load", "err %d\n", err))
@@ -142,6 +147,13 @@  void test_test_overhead(void)
 		goto cleanup;
 	test_run("fexit");
 	bpf_link__destroy(link);
+
+	/* attach fmod_ret */
+	link = bpf_program__attach_trace(fmodret_prog);
+	if (CHECK(IS_ERR(link), "attach fmod_ret", "err %ld\n", PTR_ERR(link)))
+		goto cleanup;
+	test_run("fmod_ret");
+	bpf_link__destroy(link);
 cleanup:
 	prctl(PR_SET_NAME, comm, 0L, 0L, 0L);
 	bpf_object__close(obj);
diff --git a/tools/testing/selftests/bpf/progs/test_overhead.c b/tools/testing/selftests/bpf/progs/test_overhead.c
index 56a50b25cd33..450bf819beac 100644
--- a/tools/testing/selftests/bpf/progs/test_overhead.c
+++ b/tools/testing/selftests/bpf/progs/test_overhead.c
@@ -39,4 +39,10 @@  int BPF_PROG(prog5, struct task_struct *tsk, const char *buf, bool exec)
 	return !tsk;
 }
 
+SEC("fmod_ret/__set_task_comm")
+int BPF_PROG(prog6, struct task_struct *tsk, const char *buf, bool exec)
+{
+	return !tsk;
+}
+
 char _license[] SEC("license") = "GPL";