From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752585AbdLFUwY (ORCPT ); Wed, 6 Dec 2017 15:52:24 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:44230 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752501AbdLFUwS (ORCPT ); Wed, 6 Dec 2017 15:52:18 -0500 X-Google-Smtp-Source: AGs4zMbaf5Ol+VrxDZbFoV16H02Kg9hsC1+wMPha9GIum3XIl6uMF01XEgvNJBHrL7nDnze9ph7Un7ZkdZkhS9vKBeA= MIME-Version: 1.0 In-Reply-To: <20171205012729.358860-9-songliubraving@fb.com> References: <20171205012729.358860-1-songliubraving@fb.com> <20171205012729.358860-9-songliubraving@fb.com> From: Philippe Ombredanne Date: Wed, 6 Dec 2017 21:51:36 +0100 Message-ID: Subject: Re: [PATCH v4 6/6] bpf: add new test test_many_kprobe To: Song Liu Cc: peterz@infradead.org, Steven Rostedt , Ingo Molnar , "David S. Miller" , netdev@vger.kernel.org, LKML , daniel@iogearbox.net, kernel-team@fb.com Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Song, On Tue, Dec 5, 2017 at 2:27 AM, Song Liu wrote: > 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 > Reviewed-by: Josef Bacik > Reviewed-by: Philippe Ombredanne > --- > 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 b11c1c1..ffe2c49d 100644 > --- a/samples/bpf/bpf_load.c > +++ b/samples/bpf/bpf_load.c > @@ -664,9 +664,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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#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 > Ack, and thank you very much for the usage of the SDPX license id that I reviewed. -- Cordially Philippe Ombredanne