LKML Archive on lore.kernel.org help / color / mirror / Atom feed
From: Song Liu <songliubraving@fb.com> To: <peterz@infradead.org>, <rostedt@goodmis.org>, <mingo@redhat.com>, <davem@davemloft.net>, <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>, <daniel@iogearbox.net> Cc: <kernel-team@fb.com>, Song Liu <songliubraving@fb.com> Subject: [PATCH v5 6/6] bpf: add new test test_many_kprobe Date: Wed, 6 Dec 2017 14:45:18 -0800 [thread overview] Message-ID: <20171206224518.3598254-9-songliubraving@fb.com> (raw) In-Reply-To: <20171206224518.3598254-1-songliubraving@fb.com> The test compares old text based kprobe API with perf_kprobe. Here is a sample output of this test: Creating 1000 kprobes with text-based API takes 6.979683 seconds Cleaning 1000 kprobes with text-based API takes 84.897687 seconds Creating 1000 kprobes with perf_kprobe (function name) takes 5.077558 seconds Cleaning 1000 kprobes with perf_kprobe (function name) takes 81.241354 seconds Creating 1000 kprobes with perf_kprobe (function addr) takes 5.218255 seconds Cleaning 1000 kprobes with perf_kprobe (function addr) takes 80.010731 seconds Signed-off-by: Song Liu <songliubraving@fb.com> Reviewed-by: Josef Bacik <jbacik@fb.com> Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com> --- samples/bpf/Makefile | 3 + samples/bpf/bpf_load.c | 5 +- samples/bpf/bpf_load.h | 4 + samples/bpf/test_many_kprobe_user.c | 186 ++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 samples/bpf/test_many_kprobe_user.c diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 9b4a66e..ec92f35 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -42,6 +42,7 @@ hostprogs-y += xdp_redirect hostprogs-y += xdp_redirect_map hostprogs-y += xdp_monitor hostprogs-y += syscall_tp +hostprogs-y += test_many_kprobe # Libbpf dependencies LIBBPF := ../../tools/lib/bpf/bpf.o @@ -87,6 +88,7 @@ xdp_redirect-objs := bpf_load.o $(LIBBPF) xdp_redirect_user.o xdp_redirect_map-objs := bpf_load.o $(LIBBPF) xdp_redirect_map_user.o xdp_monitor-objs := bpf_load.o $(LIBBPF) xdp_monitor_user.o syscall_tp-objs := bpf_load.o $(LIBBPF) syscall_tp_user.o +test_many_kprobe-objs := bpf_load.o $(LIBBPF) test_many_kprobe_user.o # Tell kbuild to always build the programs always := $(hostprogs-y) @@ -172,6 +174,7 @@ HOSTLOADLIBES_xdp_redirect += -lelf HOSTLOADLIBES_xdp_redirect_map += -lelf HOSTLOADLIBES_xdp_monitor += -lelf HOSTLOADLIBES_syscall_tp += -lelf +HOSTLOADLIBES_test_many_kprobe += -lelf # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: # make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c index 86e3818..49f5be5 100644 --- a/samples/bpf/bpf_load.c +++ b/samples/bpf/bpf_load.c @@ -666,9 +666,8 @@ void read_trace_pipe(void) } } -#define MAX_SYMS 300000 -static struct ksym syms[MAX_SYMS]; -static int sym_cnt; +struct ksym syms[MAX_SYMS]; +int sym_cnt; static int ksym_cmp(const void *p1, const void *p2) { diff --git a/samples/bpf/bpf_load.h b/samples/bpf/bpf_load.h index 95d6be5..6c9d584 100644 --- a/samples/bpf/bpf_load.h +++ b/samples/bpf/bpf_load.h @@ -69,6 +69,10 @@ static inline __u64 ptr_to_u64(const void *ptr) return (__u64) (unsigned long) ptr; } +#define MAX_SYMS 300000 +extern struct ksym syms[MAX_SYMS]; +extern int sym_cnt; + int load_kallsyms(void); struct ksym *ksym_search(long key); int set_link_xdp_fd(int ifindex, int fd, __u32 flags); diff --git a/samples/bpf/test_many_kprobe_user.c b/samples/bpf/test_many_kprobe_user.c new file mode 100644 index 0000000..6c111cf --- /dev/null +++ b/samples/bpf/test_many_kprobe_user.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017 Facebook + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <libelf.h> +#include <gelf.h> +#include <linux/version.h> +#include <errno.h> +#include <stdbool.h> +#include <time.h> +#include "libbpf.h" +#include "bpf_load.h" +#include "perf-sys.h" + +#define MAX_KPROBES 1000 + +#define DEBUGFS "/sys/kernel/debug/tracing/" + +int kprobes[MAX_KPROBES] = {0}; +int kprobe_count; +int perf_event_fds[MAX_KPROBES]; +const char license[] = "GPL"; + +static __u64 time_get_ns(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000000000ull + ts.tv_nsec; +} + +static int kprobe_api(char *func, void *addr, bool use_new_api) +{ + int efd; + struct perf_event_attr attr = {}; + char buf[256]; + int err, id; + + attr.sample_type = PERF_SAMPLE_RAW; + attr.sample_period = 1; + attr.wakeup_events = 1; + + if (use_new_api) { + attr.type = perf_kprobe_type; + if (func) { + attr.kprobe_func = ptr_to_u64(func); + attr.probe_offset = 0; + } else { + attr.kprobe_func = 0; + attr.kprobe_addr = ptr_to_u64(addr); + } + } else { + attr.type = PERF_TYPE_TRACEPOINT; + snprintf(buf, sizeof(buf), + "echo 'p:%s %s' >> /sys/kernel/debug/tracing/kprobe_events", + func, func); + err = system(buf); + if (err < 0) { + printf("failed to create kprobe '%s' error '%s'\n", + func, strerror(errno)); + return -1; + } + + strcpy(buf, DEBUGFS); + strcat(buf, "events/kprobes/"); + strcat(buf, func); + strcat(buf, "/id"); + efd = open(buf, O_RDONLY, 0); + if (efd < 0) { + printf("failed to open event %s\n", func); + return -1; + } + + err = read(efd, buf, sizeof(buf)); + if (err < 0 || err >= sizeof(buf)) { + printf("read from '%s' failed '%s'\n", func, + strerror(errno)); + return -1; + } + + close(efd); + buf[err] = 0; + id = atoi(buf); + attr.config = id; + } + + attr.size = sizeof(attr); + efd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, + -1/*group_fd*/, 0); + + return efd; +} + +static int select_kprobes(void) +{ + int fd; + int i; + + load_kallsyms(); + + kprobe_count = 0; + for (i = 0; i < sym_cnt; i++) { + if (strstr(syms[i].name, ".")) + continue; + fd = kprobe_api(syms[i].name, NULL, false); + if (fd < 0) + continue; + close(fd); + kprobes[kprobe_count] = i; + if (++kprobe_count >= MAX_KPROBES) + break; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + int i; + __u64 start_time; + + select_kprobes(); + + /* clean all trace_kprobe */ + i = system("echo \"\" > /sys/kernel/debug/tracing/kprobe_events"); + + /* test text based API */ + start_time = time_get_ns(); + for (i = 0; i < kprobe_count; i++) + perf_event_fds[i] = kprobe_api(syms[kprobes[i]].name, + NULL, false); + printf("Creating %d kprobes with text-based API takes %f seconds\n", + kprobe_count, (time_get_ns() - start_time) / 1000000000.0); + + start_time = time_get_ns(); + for (i = 0; i < kprobe_count; i++) + if (perf_event_fds[i] > 0) + close(perf_event_fds[i]); + i = system("echo \"\" > /sys/kernel/debug/tracing/kprobe_events"); + printf("Cleaning %d kprobes with text-based API takes %f seconds\n", + kprobe_count, (time_get_ns() - start_time) / 1000000000.0); + + get_perf_kprobe_type_id(); + if (perf_kprobe_type == -1) { + printf("The kernel does support perf_kprobe.\n" + "Existing...\n"); + return 0; + } + + /* test perf_kprobe API, with function names */ + start_time = time_get_ns(); + for (i = 0; i < kprobe_count; i++) + perf_event_fds[i] = kprobe_api(syms[kprobes[i]].name, + NULL, true); + printf("Creating %d kprobes with perf_kprobe (function name) takes %f seconds\n", + kprobe_count, (time_get_ns() - start_time) / 1000000000.0); + + start_time = time_get_ns(); + for (i = 0; i < kprobe_count; i++) + if (perf_event_fds[i] > 0) + close(perf_event_fds[i]); + printf("Cleaning %d kprobes with perf_kprobe (function name) takes %f seconds\n", + kprobe_count, (time_get_ns() - start_time) / 1000000000.0); + + /* test perf_kprobe API, with function address */ + start_time = time_get_ns(); + for (i = 0; i < kprobe_count; i++) + perf_event_fds[i] = kprobe_api( + NULL, (void *)(syms[kprobes[i]].addr), true); + printf("Creating %d kprobes with perf_kprobe (function addr) takes %f seconds\n", + kprobe_count, (time_get_ns() - start_time) / 1000000000.0); + + start_time = time_get_ns(); + for (i = 0; i < kprobe_count; i++) + if (perf_event_fds[i] > 0) + close(perf_event_fds[i]); + printf("Cleaning %d kprobes with perf_kprobe (function addr) takes %f seconds\n", + kprobe_count, (time_get_ns() - start_time) / 1000000000.0); + return 0; +} -- 2.9.5
next prev parent reply other threads:[~2017-12-06 22:46 UTC|newest] Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-12-06 22:45 [PATCH v5 0/6] enable creating [k,u]probe with perf_event_open Song Liu 2017-12-06 22:45 ` [PATCH v5] bcc: Try use new API to create " Song Liu 2017-12-06 22:45 ` [PATCH v5] perf_event_open.2: add type kprobe and uprobe Song Liu 2017-12-06 22:45 ` [PATCH v5 1/6] perf: prepare perf_event.h for new types perf_kprobe and perf_uprobe Song Liu 2018-02-06 11:52 ` [tip:perf/core] perf/core: Prepare perf_event.h for new types: 'perf_kprobe' and 'perf_uprobe' tip-bot for Song Liu 2017-12-06 22:45 ` [PATCH v5 2/6] perf: copy new perf_event.h to tools/include/uapi Song Liu 2018-02-06 11:52 ` [tip:perf/core] perf/headers: Sync new perf_event.h with the tools/include/uapi version tip-bot for Song Liu 2018-02-13 22:38 ` Alexei Starovoitov 2018-02-14 7:51 ` Ingo Molnar 2017-12-06 22:45 ` [PATCH v5 3/6] perf: implement pmu perf_kprobe Song Liu 2017-12-20 10:03 ` Peter Zijlstra 2017-12-20 10:14 ` Peter Zijlstra 2017-12-20 18:10 ` Song Liu 2017-12-20 21:25 ` Peter Zijlstra 2017-12-20 22:05 ` Song Liu 2018-02-06 11:59 ` [tip:perf/core] perf/core: Implement the 'perf_kprobe' PMU tip-bot for Song Liu 2017-12-06 22:45 ` [PATCH v5 4/6] perf: implement pmu perf_uprobe Song Liu 2018-02-06 11:59 ` [tip:perf/core] perf/core: Implement the 'perf_uprobe' PMU tip-bot for Song Liu 2017-12-06 22:45 ` [PATCH v5 5/6] bpf: add option for bpf_load.c to use perf_kprobe Song Liu 2017-12-06 22:45 ` Song Liu [this message] 2017-12-07 10:23 ` [PATCH v5 0/6] enable creating [k,u]probe with perf_event_open Philippe Ombredanne 2017-12-08 19:57 ` Daniel Borkmann 2017-12-19 17:24 ` Song Liu 2017-12-19 20:25 ` Peter Zijlstra 2018-04-10 4:45 ` Ravi Bangoria 2018-04-10 4:54 ` Alexei Starovoitov
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=20171206224518.3598254-9-songliubraving@fb.com \ --to=songliubraving@fb.com \ --cc=daniel@iogearbox.net \ --cc=davem@davemloft.net \ --cc=kernel-team@fb.com \ --cc=linux-kernel@vger.kernel.org \ --cc=mingo@redhat.com \ --cc=netdev@vger.kernel.org \ --cc=peterz@infradead.org \ --cc=rostedt@goodmis.org \ /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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).