126e90931SAlexei Starovoitov /* Copyright (c) 2016 Facebook 226e90931SAlexei Starovoitov * 326e90931SAlexei Starovoitov * This program is free software; you can redistribute it and/or 426e90931SAlexei Starovoitov * modify it under the terms of version 2 of the GNU General Public 526e90931SAlexei Starovoitov * License as published by the Free Software Foundation. 626e90931SAlexei Starovoitov */ 726e90931SAlexei Starovoitov #define _GNU_SOURCE 826e90931SAlexei Starovoitov #include <sched.h> 926e90931SAlexei Starovoitov #include <stdio.h> 1026e90931SAlexei Starovoitov #include <sys/types.h> 1126e90931SAlexei Starovoitov #include <asm/unistd.h> 1226e90931SAlexei Starovoitov #include <unistd.h> 1326e90931SAlexei Starovoitov #include <assert.h> 1426e90931SAlexei Starovoitov #include <sys/wait.h> 1526e90931SAlexei Starovoitov #include <stdlib.h> 1626e90931SAlexei Starovoitov #include <signal.h> 1726e90931SAlexei Starovoitov #include <linux/bpf.h> 1826e90931SAlexei Starovoitov #include <string.h> 1926e90931SAlexei Starovoitov #include <time.h> 2077e63534SNaveen N. Rao #include <sys/resource.h> 2126e90931SAlexei Starovoitov #include "libbpf.h" 2226e90931SAlexei Starovoitov #include "bpf_load.h" 2326e90931SAlexei Starovoitov 2426e90931SAlexei Starovoitov #define MAX_CNT 1000000 2526e90931SAlexei Starovoitov 2626e90931SAlexei Starovoitov static __u64 time_get_ns(void) 2726e90931SAlexei Starovoitov { 2826e90931SAlexei Starovoitov struct timespec ts; 2926e90931SAlexei Starovoitov 3026e90931SAlexei Starovoitov clock_gettime(CLOCK_MONOTONIC, &ts); 3126e90931SAlexei Starovoitov return ts.tv_sec * 1000000000ull + ts.tv_nsec; 3226e90931SAlexei Starovoitov } 3326e90931SAlexei Starovoitov 3426e90931SAlexei Starovoitov #define HASH_PREALLOC (1 << 0) 3526e90931SAlexei Starovoitov #define PERCPU_HASH_PREALLOC (1 << 1) 3626e90931SAlexei Starovoitov #define HASH_KMALLOC (1 << 2) 3726e90931SAlexei Starovoitov #define PERCPU_HASH_KMALLOC (1 << 3) 38*5db58fafSMartin KaFai Lau #define LRU_HASH_PREALLOC (1 << 4) 39*5db58fafSMartin KaFai Lau #define PERCPU_LRU_HASH_PREALLOC (1 << 5) 4026e90931SAlexei Starovoitov 4126e90931SAlexei Starovoitov static int test_flags = ~0; 4226e90931SAlexei Starovoitov 4326e90931SAlexei Starovoitov static void test_hash_prealloc(int cpu) 4426e90931SAlexei Starovoitov { 4526e90931SAlexei Starovoitov __u64 start_time; 4626e90931SAlexei Starovoitov int i; 4726e90931SAlexei Starovoitov 4826e90931SAlexei Starovoitov start_time = time_get_ns(); 4926e90931SAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 5026e90931SAlexei Starovoitov syscall(__NR_getuid); 5126e90931SAlexei Starovoitov printf("%d:hash_map_perf pre-alloc %lld events per sec\n", 5226e90931SAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 5326e90931SAlexei Starovoitov } 5426e90931SAlexei Starovoitov 55*5db58fafSMartin KaFai Lau static void test_lru_hash_prealloc(int cpu) 56*5db58fafSMartin KaFai Lau { 57*5db58fafSMartin KaFai Lau __u64 start_time; 58*5db58fafSMartin KaFai Lau int i; 59*5db58fafSMartin KaFai Lau 60*5db58fafSMartin KaFai Lau start_time = time_get_ns(); 61*5db58fafSMartin KaFai Lau for (i = 0; i < MAX_CNT; i++) 62*5db58fafSMartin KaFai Lau syscall(__NR_getpid); 63*5db58fafSMartin KaFai Lau printf("%d:lru_hash_map_perf pre-alloc %lld events per sec\n", 64*5db58fafSMartin KaFai Lau cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 65*5db58fafSMartin KaFai Lau } 66*5db58fafSMartin KaFai Lau 67*5db58fafSMartin KaFai Lau static void test_percpu_lru_hash_prealloc(int cpu) 68*5db58fafSMartin KaFai Lau { 69*5db58fafSMartin KaFai Lau __u64 start_time; 70*5db58fafSMartin KaFai Lau int i; 71*5db58fafSMartin KaFai Lau 72*5db58fafSMartin KaFai Lau start_time = time_get_ns(); 73*5db58fafSMartin KaFai Lau for (i = 0; i < MAX_CNT; i++) 74*5db58fafSMartin KaFai Lau syscall(__NR_getppid); 75*5db58fafSMartin KaFai Lau printf("%d:lru_hash_map_perf pre-alloc %lld events per sec\n", 76*5db58fafSMartin KaFai Lau cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 77*5db58fafSMartin KaFai Lau } 78*5db58fafSMartin KaFai Lau 7926e90931SAlexei Starovoitov static void test_percpu_hash_prealloc(int cpu) 8026e90931SAlexei Starovoitov { 8126e90931SAlexei Starovoitov __u64 start_time; 8226e90931SAlexei Starovoitov int i; 8326e90931SAlexei Starovoitov 8426e90931SAlexei Starovoitov start_time = time_get_ns(); 8526e90931SAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 8626e90931SAlexei Starovoitov syscall(__NR_geteuid); 8726e90931SAlexei Starovoitov printf("%d:percpu_hash_map_perf pre-alloc %lld events per sec\n", 8826e90931SAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 8926e90931SAlexei Starovoitov } 9026e90931SAlexei Starovoitov 9126e90931SAlexei Starovoitov static void test_hash_kmalloc(int cpu) 9226e90931SAlexei Starovoitov { 9326e90931SAlexei Starovoitov __u64 start_time; 9426e90931SAlexei Starovoitov int i; 9526e90931SAlexei Starovoitov 9626e90931SAlexei Starovoitov start_time = time_get_ns(); 9726e90931SAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 9826e90931SAlexei Starovoitov syscall(__NR_getgid); 9926e90931SAlexei Starovoitov printf("%d:hash_map_perf kmalloc %lld events per sec\n", 10026e90931SAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 10126e90931SAlexei Starovoitov } 10226e90931SAlexei Starovoitov 10326e90931SAlexei Starovoitov static void test_percpu_hash_kmalloc(int cpu) 10426e90931SAlexei Starovoitov { 10526e90931SAlexei Starovoitov __u64 start_time; 10626e90931SAlexei Starovoitov int i; 10726e90931SAlexei Starovoitov 10826e90931SAlexei Starovoitov start_time = time_get_ns(); 10926e90931SAlexei Starovoitov for (i = 0; i < MAX_CNT; i++) 11026e90931SAlexei Starovoitov syscall(__NR_getegid); 11126e90931SAlexei Starovoitov printf("%d:percpu_hash_map_perf kmalloc %lld events per sec\n", 11226e90931SAlexei Starovoitov cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); 11326e90931SAlexei Starovoitov } 11426e90931SAlexei Starovoitov 11526e90931SAlexei Starovoitov static void loop(int cpu) 11626e90931SAlexei Starovoitov { 11726e90931SAlexei Starovoitov cpu_set_t cpuset; 11826e90931SAlexei Starovoitov 11926e90931SAlexei Starovoitov CPU_ZERO(&cpuset); 12026e90931SAlexei Starovoitov CPU_SET(cpu, &cpuset); 12126e90931SAlexei Starovoitov sched_setaffinity(0, sizeof(cpuset), &cpuset); 12226e90931SAlexei Starovoitov 12326e90931SAlexei Starovoitov if (test_flags & HASH_PREALLOC) 12426e90931SAlexei Starovoitov test_hash_prealloc(cpu); 12526e90931SAlexei Starovoitov 12626e90931SAlexei Starovoitov if (test_flags & PERCPU_HASH_PREALLOC) 12726e90931SAlexei Starovoitov test_percpu_hash_prealloc(cpu); 12826e90931SAlexei Starovoitov 12926e90931SAlexei Starovoitov if (test_flags & HASH_KMALLOC) 13026e90931SAlexei Starovoitov test_hash_kmalloc(cpu); 13126e90931SAlexei Starovoitov 13226e90931SAlexei Starovoitov if (test_flags & PERCPU_HASH_KMALLOC) 13326e90931SAlexei Starovoitov test_percpu_hash_kmalloc(cpu); 134*5db58fafSMartin KaFai Lau 135*5db58fafSMartin KaFai Lau if (test_flags & LRU_HASH_PREALLOC) 136*5db58fafSMartin KaFai Lau test_lru_hash_prealloc(cpu); 137*5db58fafSMartin KaFai Lau 138*5db58fafSMartin KaFai Lau if (test_flags & PERCPU_LRU_HASH_PREALLOC) 139*5db58fafSMartin KaFai Lau test_percpu_lru_hash_prealloc(cpu); 14026e90931SAlexei Starovoitov } 14126e90931SAlexei Starovoitov 14226e90931SAlexei Starovoitov static void run_perf_test(int tasks) 14326e90931SAlexei Starovoitov { 14426e90931SAlexei Starovoitov pid_t pid[tasks]; 14526e90931SAlexei Starovoitov int i; 14626e90931SAlexei Starovoitov 14726e90931SAlexei Starovoitov for (i = 0; i < tasks; i++) { 14826e90931SAlexei Starovoitov pid[i] = fork(); 14926e90931SAlexei Starovoitov if (pid[i] == 0) { 15026e90931SAlexei Starovoitov loop(i); 15126e90931SAlexei Starovoitov exit(0); 15226e90931SAlexei Starovoitov } else if (pid[i] == -1) { 15326e90931SAlexei Starovoitov printf("couldn't spawn #%d process\n", i); 15426e90931SAlexei Starovoitov exit(1); 15526e90931SAlexei Starovoitov } 15626e90931SAlexei Starovoitov } 15726e90931SAlexei Starovoitov for (i = 0; i < tasks; i++) { 15826e90931SAlexei Starovoitov int status; 15926e90931SAlexei Starovoitov 16026e90931SAlexei Starovoitov assert(waitpid(pid[i], &status, 0) == pid[i]); 16126e90931SAlexei Starovoitov assert(status == 0); 16226e90931SAlexei Starovoitov } 16326e90931SAlexei Starovoitov } 16426e90931SAlexei Starovoitov 16526e90931SAlexei Starovoitov int main(int argc, char **argv) 16626e90931SAlexei Starovoitov { 16726e90931SAlexei Starovoitov struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 16826e90931SAlexei Starovoitov char filename[256]; 16926e90931SAlexei Starovoitov int num_cpu = 8; 17026e90931SAlexei Starovoitov 17126e90931SAlexei Starovoitov snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 17226e90931SAlexei Starovoitov setrlimit(RLIMIT_MEMLOCK, &r); 17326e90931SAlexei Starovoitov 17426e90931SAlexei Starovoitov if (argc > 1) 17526e90931SAlexei Starovoitov test_flags = atoi(argv[1]) ? : test_flags; 17626e90931SAlexei Starovoitov 17726e90931SAlexei Starovoitov if (argc > 2) 17826e90931SAlexei Starovoitov num_cpu = atoi(argv[2]) ? : num_cpu; 17926e90931SAlexei Starovoitov 18026e90931SAlexei Starovoitov if (load_bpf_file(filename)) { 18126e90931SAlexei Starovoitov printf("%s", bpf_log_buf); 18226e90931SAlexei Starovoitov return 1; 18326e90931SAlexei Starovoitov } 18426e90931SAlexei Starovoitov 18526e90931SAlexei Starovoitov run_perf_test(num_cpu); 18626e90931SAlexei Starovoitov 18726e90931SAlexei Starovoitov return 0; 18826e90931SAlexei Starovoitov } 189