lkml.org 
[lkml]   [2017]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 6/6] bpf: add new test test_many_kprobe
    Date
    The test compares old text based kprobe API with PERF_TYPE_PROBE.

    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_TYPE_PROBE (function name) takes 5.077558 seconds
    Cleaning 1000 kprobes with PERF_TYPE_PROBE (function name) takes 81.241354 seconds
    Creating 1000 kprobes with PERF_TYPE_PROBE (function addr) takes 5.218255 seconds
    Cleaning 1000 kprobes with PERF_TYPE_PROBE (function addr) takes 80.010731 seconds

    Signed-off-by: Song Liu <songliubraving@fb.com>
    Reviewed-by: Josef Bacik <jbacik@fb.com>
    ---
    samples/bpf/Makefile | 3 +
    samples/bpf/bpf_load.c | 5 +-
    samples/bpf/bpf_load.h | 4 +
    samples/bpf/test_many_kprobe_user.c | 184 ++++++++++++++++++++++++++++++++++++
    4 files changed, 193 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 dc6d843..ab514c1 100644
    --- a/samples/bpf/bpf_load.c
    +++ b/samples/bpf/bpf_load.c
    @@ -637,9 +637,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 e7a8a21..16bc263 100644
    --- a/samples/bpf/bpf_load.h
    +++ b/samples/bpf/bpf_load.h
    @@ -67,6 +67,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..70b680e
    --- /dev/null
    +++ b/samples/bpf/test_many_kprobe_user.c
    @@ -0,0 +1,184 @@
    +/* Copyright (c) 2017 Facebook
    + *
    + * This program is free software; you can redistribute it and/or
    + * modify it under the terms of version 2 of the GNU General Public
    + * License as published by the Free Software Foundation.
    + */
    +#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 = {};
    + struct probe_desc pd;
    + 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_TYPE_PROBE;
    + if (func) {
    + pd.func = ptr_to_u64(func);
    + pd.offset = 0;
    + } else {
    + pd.func = 0;
    + pd.offset = ptr_to_u64(addr);
    + }
    +
    + attr.probe_desc = ptr_to_u64(&pd);
    + } 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;
    + }
    +
    + 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, true);
    + 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);
    +
    + /* test PERF_TYPE_PROBE 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_TYPE_PROBE (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_TYPE_PROBE (function name) takes %f seconds\n",
    + kprobe_count, (time_get_ns() - start_time) / 1000000000.0);
    +
    + /* test PERF_TYPE_PROBE 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_TYPE_PROBE (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_TYPE_PROBE (function addr) takes %f seconds\n",
    + kprobe_count, (time_get_ns() - start_time) / 1000000000.0);
    + return 0;
    +}
    --
    2.9.5
    \
     
     \ /
      Last update: 2017-11-15 18:25    [W:3.732 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site