^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Copyright (c) 2016 Facebook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #define _GNU_SOURCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sys/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sys/resource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <bpf/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "bpf_load.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MAX_CNT 1000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static __u64 time_get_ns(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct timespec ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) clock_gettime(CLOCK_MONOTONIC, &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return ts.tv_sec * 1000000000ull + ts.tv_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static void test_task_rename(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) __u64 start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) char buf[] = "test\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int i, fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) fd = open("/proc/self/comm", O_WRONLY|O_TRUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) printf("couldn't open /proc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) start_time = time_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) for (i = 0; i < MAX_CNT; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (write(fd, buf, sizeof(buf)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) printf("task rename failed: %s\n", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) printf("task_rename:%d: %lld events per sec\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static void test_urandom_read(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) __u64 start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) char buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int i, fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) fd = open("/dev/urandom", O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) printf("couldn't open /dev/urandom\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) start_time = time_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) for (i = 0; i < MAX_CNT; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (read(fd, buf, sizeof(buf)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) printf("failed to read from /dev/urandom: %s\n", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) printf("urandom_read:%d: %lld events per sec\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static void loop(int cpu, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) cpu_set_t cpuset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) CPU_ZERO(&cpuset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) CPU_SET(cpu, &cpuset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) sched_setaffinity(0, sizeof(cpuset), &cpuset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (flags & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) test_task_rename(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (flags & 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) test_urandom_read(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static void run_perf_test(int tasks, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) pid_t pid[tasks];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) for (i = 0; i < tasks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pid[i] = fork();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (pid[i] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) loop(i, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) exit(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) } else if (pid[i] == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) printf("couldn't spawn #%d process\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) for (i = 0; i < tasks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) assert(waitpid(pid[i], &status, 0) == pid[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) assert(status == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void unload_progs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) close(prog_fd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) close(prog_fd[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) close(event_fd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) close(event_fd[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) char filename[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int num_cpu = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int test_flags = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) setrlimit(RLIMIT_MEMLOCK, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (argc > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) test_flags = atoi(argv[1]) ? : test_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (argc > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) num_cpu = atoi(argv[2]) ? : num_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (test_flags & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) printf("BASE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) run_perf_test(num_cpu, test_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (test_flags & 0xC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) snprintf(filename, sizeof(filename),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "%s_kprobe_kern.o", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (load_bpf_file(filename)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) printf("%s", bpf_log_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) printf("w/KPROBE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) run_perf_test(num_cpu, test_flags >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unload_progs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (test_flags & 0x30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) snprintf(filename, sizeof(filename),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) "%s_tp_kern.o", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (load_bpf_file(filename)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) printf("%s", bpf_log_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) printf("w/TRACEPOINT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) run_perf_test(num_cpu, test_flags >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unload_progs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (test_flags & 0xC0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) snprintf(filename, sizeof(filename),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) "%s_raw_tp_kern.o", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (load_bpf_file(filename)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) printf("%s", bpf_log_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) printf("w/RAW_TRACEPOINT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) run_perf_test(num_cpu, test_flags >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) unload_progs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }