linux/samples/bpf/test_overhead_user.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* Copyright (c) 2016 Facebook
   3 */
   4#define _GNU_SOURCE
   5#include <sched.h>
   6#include <errno.h>
   7#include <stdio.h>
   8#include <sys/types.h>
   9#include <asm/unistd.h>
  10#include <fcntl.h>
  11#include <unistd.h>
  12#include <assert.h>
  13#include <sys/wait.h>
  14#include <stdlib.h>
  15#include <signal.h>
  16#include <linux/bpf.h>
  17#include <string.h>
  18#include <time.h>
  19#include <sys/resource.h>
  20#include <bpf/bpf.h>
  21#include <bpf/libbpf.h>
  22
  23#define MAX_CNT 1000000
  24
  25static struct bpf_link *links[2];
  26static struct bpf_object *obj;
  27static int cnt;
  28
  29static __u64 time_get_ns(void)
  30{
  31        struct timespec ts;
  32
  33        clock_gettime(CLOCK_MONOTONIC, &ts);
  34        return ts.tv_sec * 1000000000ull + ts.tv_nsec;
  35}
  36
  37static void test_task_rename(int cpu)
  38{
  39        __u64 start_time;
  40        char buf[] = "test\n";
  41        int i, fd;
  42
  43        fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);
  44        if (fd < 0) {
  45                printf("couldn't open /proc\n");
  46                exit(1);
  47        }
  48        start_time = time_get_ns();
  49        for (i = 0; i < MAX_CNT; i++) {
  50                if (write(fd, buf, sizeof(buf)) < 0) {
  51                        printf("task rename failed: %s\n", strerror(errno));
  52                        close(fd);
  53                        return;
  54                }
  55        }
  56        printf("task_rename:%d: %lld events per sec\n",
  57               cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
  58        close(fd);
  59}
  60
  61static void test_urandom_read(int cpu)
  62{
  63        __u64 start_time;
  64        char buf[4];
  65        int i, fd;
  66
  67        fd = open("/dev/urandom", O_RDONLY);
  68        if (fd < 0) {
  69                printf("couldn't open /dev/urandom\n");
  70                exit(1);
  71        }
  72        start_time = time_get_ns();
  73        for (i = 0; i < MAX_CNT; i++) {
  74                if (read(fd, buf, sizeof(buf)) < 0) {
  75                        printf("failed to read from /dev/urandom: %s\n", strerror(errno));
  76                        close(fd);
  77                        return;
  78                }
  79        }
  80        printf("urandom_read:%d: %lld events per sec\n",
  81               cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
  82        close(fd);
  83}
  84
  85static void loop(int cpu, int flags)
  86{
  87        cpu_set_t cpuset;
  88
  89        CPU_ZERO(&cpuset);
  90        CPU_SET(cpu, &cpuset);
  91        sched_setaffinity(0, sizeof(cpuset), &cpuset);
  92
  93        if (flags & 1)
  94                test_task_rename(cpu);
  95        if (flags & 2)
  96                test_urandom_read(cpu);
  97}
  98
  99static void run_perf_test(int tasks, int flags)
 100{
 101        pid_t pid[tasks];
 102        int i;
 103
 104        for (i = 0; i < tasks; i++) {
 105                pid[i] = fork();
 106                if (pid[i] == 0) {
 107                        loop(i, flags);
 108                        exit(0);
 109                } else if (pid[i] == -1) {
 110                        printf("couldn't spawn #%d process\n", i);
 111                        exit(1);
 112                }
 113        }
 114        for (i = 0; i < tasks; i++) {
 115                int status;
 116
 117                assert(waitpid(pid[i], &status, 0) == pid[i]);
 118                assert(status == 0);
 119        }
 120}
 121
 122static int load_progs(char *filename)
 123{
 124        struct bpf_program *prog;
 125        int err = 0;
 126
 127        obj = bpf_object__open_file(filename, NULL);
 128        err = libbpf_get_error(obj);
 129        if (err < 0) {
 130                fprintf(stderr, "ERROR: opening BPF object file failed\n");
 131                return err;
 132        }
 133
 134        /* load BPF program */
 135        err = bpf_object__load(obj);
 136        if (err < 0) {
 137                fprintf(stderr, "ERROR: loading BPF object file failed\n");
 138                return err;
 139        }
 140
 141        bpf_object__for_each_program(prog, obj) {
 142                links[cnt] = bpf_program__attach(prog);
 143                err = libbpf_get_error(links[cnt]);
 144                if (err < 0) {
 145                        fprintf(stderr, "ERROR: bpf_program__attach failed\n");
 146                        links[cnt] = NULL;
 147                        return err;
 148                }
 149                cnt++;
 150        }
 151
 152        return err;
 153}
 154
 155static void unload_progs(void)
 156{
 157        while (cnt)
 158                bpf_link__destroy(links[--cnt]);
 159
 160        bpf_object__close(obj);
 161}
 162
 163int main(int argc, char **argv)
 164{
 165        int num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
 166        int test_flags = ~0;
 167        char filename[256];
 168        int err = 0;
 169
 170
 171        if (argc > 1)
 172                test_flags = atoi(argv[1]) ? : test_flags;
 173        if (argc > 2)
 174                num_cpu = atoi(argv[2]) ? : num_cpu;
 175
 176        if (test_flags & 0x3) {
 177                printf("BASE\n");
 178                run_perf_test(num_cpu, test_flags);
 179        }
 180
 181        if (test_flags & 0xC) {
 182                snprintf(filename, sizeof(filename),
 183                         "%s_kprobe_kern.o", argv[0]);
 184
 185                printf("w/KPROBE\n");
 186                err = load_progs(filename);
 187                if (!err)
 188                        run_perf_test(num_cpu, test_flags >> 2);
 189
 190                unload_progs();
 191        }
 192
 193        if (test_flags & 0x30) {
 194                snprintf(filename, sizeof(filename),
 195                         "%s_tp_kern.o", argv[0]);
 196                printf("w/TRACEPOINT\n");
 197                err = load_progs(filename);
 198                if (!err)
 199                        run_perf_test(num_cpu, test_flags >> 4);
 200
 201                unload_progs();
 202        }
 203
 204        if (test_flags & 0xC0) {
 205                snprintf(filename, sizeof(filename),
 206                         "%s_raw_tp_kern.o", argv[0]);
 207                printf("w/RAW_TRACEPOINT\n");
 208                err = load_progs(filename);
 209                if (!err)
 210                        run_perf_test(num_cpu, test_flags >> 6);
 211
 212                unload_progs();
 213        }
 214
 215        return err;
 216}
 217