1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2629cc356SHitoshi Mitake /* 3629cc356SHitoshi Mitake * builtin-bench.c 4629cc356SHitoshi Mitake * 54157922aSIngo Molnar * General benchmarking collections provided by perf 6629cc356SHitoshi Mitake * 7629cc356SHitoshi Mitake * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 8629cc356SHitoshi Mitake */ 9629cc356SHitoshi Mitake 10629cc356SHitoshi Mitake /* 114157922aSIngo Molnar * Available benchmark collection list: 12629cc356SHitoshi Mitake * 134157922aSIngo Molnar * sched ... scheduler and IPC performance 14c2a08203SDavidlohr Bueso * syscall ... System call performance 15827f3b49SHitoshi Mitake * mem ... memory access performance 164157922aSIngo Molnar * numa ... NUMA scheduling and MM performance 17a0439711SDavidlohr Bueso * futex ... Futex performance 18121dd9eaSDavidlohr Bueso * epoll ... Event poll performance 19629cc356SHitoshi Mitake */ 204b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 21629cc356SHitoshi Mitake #include "builtin.h" 22629cc356SHitoshi Mitake #include "bench/bench.h" 23629cc356SHitoshi Mitake 2416203e9cSArnaldo Carvalho de Melo #include <locale.h> 25629cc356SHitoshi Mitake #include <stdio.h> 26629cc356SHitoshi Mitake #include <stdlib.h> 27629cc356SHitoshi Mitake #include <string.h> 284157922aSIngo Molnar #include <sys/prctl.h> 297f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h> 30629cc356SHitoshi Mitake 31b0ad8ea6SArnaldo Carvalho de Melo typedef int (*bench_fn_t)(int argc, const char **argv); 324157922aSIngo Molnar 334157922aSIngo Molnar struct bench { 34629cc356SHitoshi Mitake const char *name; 35629cc356SHitoshi Mitake const char *summary; 364157922aSIngo Molnar bench_fn_t fn; 37629cc356SHitoshi Mitake }; 38629cc356SHitoshi Mitake 3989fe808aSIngo Molnar #ifdef HAVE_LIBNUMA_SUPPORT 404157922aSIngo Molnar static struct bench numa_benchmarks[] = { 414157922aSIngo Molnar { "mem", "Benchmark for NUMA workloads", bench_numa }, 42aa254af2SIngo Molnar { "all", "Run all NUMA benchmarks", NULL }, 434157922aSIngo Molnar { NULL, NULL, NULL } 441c13f3c9SIngo Molnar }; 4579d824e3SPeter Hurley #endif 461c13f3c9SIngo Molnar 474157922aSIngo Molnar static struct bench sched_benchmarks[] = { 484157922aSIngo Molnar { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging }, 494157922aSIngo Molnar { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe }, 507d5cb68aSAndrei Vagin { "seccomp-notify", "Benchmark for seccomp user notify", bench_sched_seccomp_notify}, 51aa254af2SIngo Molnar { "all", "Run all scheduler benchmarks", NULL }, 524157922aSIngo Molnar { NULL, NULL, NULL } 53629cc356SHitoshi Mitake }; 54629cc356SHitoshi Mitake 55c2a08203SDavidlohr Bueso static struct bench syscall_benchmarks[] = { 56c2a08203SDavidlohr Bueso { "basic", "Benchmark for basic getppid(2) calls", bench_syscall_basic }, 57391f84e5STiezhu Yang { "getpgid", "Benchmark for getpgid(2) calls", bench_syscall_getpgid }, 58ece7f7c0STiezhu Yang { "fork", "Benchmark for fork(2) calls", bench_syscall_fork }, 59540f8b56STiezhu Yang { "execve", "Benchmark for execve(2) calls", bench_syscall_execve }, 60c2a08203SDavidlohr Bueso { "all", "Run all syscall benchmarks", NULL }, 61c2a08203SDavidlohr Bueso { NULL, NULL, NULL }, 62c2a08203SDavidlohr Bueso }; 63c2a08203SDavidlohr Bueso 644157922aSIngo Molnar static struct bench mem_benchmarks[] = { 6513b1fdceSIngo Molnar { "memcpy", "Benchmark for memcpy() functions", bench_mem_memcpy }, 6613b1fdceSIngo Molnar { "memset", "Benchmark for memset() functions", bench_mem_memset }, 677c43b0c1SIan Rogers { "find_bit", "Benchmark for find_bit() functions", bench_mem_find_bit }, 68aa254af2SIngo Molnar { "all", "Run all memory access benchmarks", NULL }, 694157922aSIngo Molnar { NULL, NULL, NULL } 70827f3b49SHitoshi Mitake }; 71827f3b49SHitoshi Mitake 72a0439711SDavidlohr Bueso static struct bench futex_benchmarks[] = { 73a0439711SDavidlohr Bueso { "hash", "Benchmark for futex hash table", bench_futex_hash }, 7427db7830SDavidlohr Bueso { "wake", "Benchmark for futex wake calls", bench_futex_wake }, 75d65817b4SDavidlohr Bueso { "wake-parallel", "Benchmark for parallel futex wake calls", bench_futex_wake_parallel }, 760fb298cfSDavidlohr Bueso { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue }, 77d2f3f5d2SDavidlohr Bueso /* pi-futexes */ 78d2f3f5d2SDavidlohr Bueso { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi }, 79aa254af2SIngo Molnar { "all", "Run all futex benchmarks", NULL }, 80a0439711SDavidlohr Bueso { NULL, NULL, NULL } 81a0439711SDavidlohr Bueso }; 82a0439711SDavidlohr Bueso 83ba35fe93SArnaldo Carvalho de Melo #ifdef HAVE_EVENTFD_SUPPORT 84121dd9eaSDavidlohr Bueso static struct bench epoll_benchmarks[] = { 85121dd9eaSDavidlohr Bueso { "wait", "Benchmark epoll concurrent epoll_waits", bench_epoll_wait }, 86231457ecSDavidlohr Bueso { "ctl", "Benchmark epoll concurrent epoll_ctls", bench_epoll_ctl }, 87121dd9eaSDavidlohr Bueso { "all", "Run all futex benchmarks", NULL }, 88121dd9eaSDavidlohr Bueso { NULL, NULL, NULL } 89121dd9eaSDavidlohr Bueso }; 90ba35fe93SArnaldo Carvalho de Melo #endif // HAVE_EVENTFD_SUPPORT 91121dd9eaSDavidlohr Bueso 922a4b5166SIan Rogers static struct bench internals_benchmarks[] = { 932a4b5166SIan Rogers { "synthesize", "Benchmark perf event synthesis", bench_synthesize }, 9451876bd4SIan Rogers { "kallsyms-parse", "Benchmark kallsyms parsing", bench_kallsyms_parse }, 950bf02a0dSNamhyung Kim { "inject-build-id", "Benchmark build-id injection", bench_inject_build_id }, 964241eabfSRiccardo Mancini { "evlist-open-close", "Benchmark evlist open and close", bench_evlist_open_close }, 97f6a7bbbfSNamhyung Kim { "pmu-scan", "Benchmark sysfs PMU info scanning", bench_pmu_scan }, 982a4b5166SIan Rogers { NULL, NULL, NULL } 992a4b5166SIan Rogers }; 1002a4b5166SIan Rogers 10168a6772fSDmitry Vyukov static struct bench breakpoint_benchmarks[] = { 10268a6772fSDmitry Vyukov { "thread", "Benchmark thread start/finish with breakpoints", bench_breakpoint_thread}, 10368a6772fSDmitry Vyukov { "enable", "Benchmark breakpoint enable/disable", bench_breakpoint_enable}, 10468a6772fSDmitry Vyukov { "all", "Run all breakpoint benchmarks", NULL}, 10568a6772fSDmitry Vyukov { NULL, NULL, NULL }, 10668a6772fSDmitry Vyukov }; 10768a6772fSDmitry Vyukov 1082df27071SArnaldo Carvalho de Melo static struct bench uprobe_benchmarks[] = { 1092df27071SArnaldo Carvalho de Melo { "baseline", "Baseline libc usleep(1000) call", bench_uprobe_baseline, }, 1106af5e4cfSArnaldo Carvalho de Melo { "empty", "Attach empty BPF prog to uprobe on usleep, system wide", bench_uprobe_empty, }, 1117b47623bSArnaldo Carvalho de Melo { "trace_printk", "Attach trace_printk BPF prog to uprobe on usleep syswide", bench_uprobe_trace_printk, }, 112*988052f4SIan Rogers { "empty_ret", "Attach empty BPF prog to uretprobe on usleep, system wide", bench_uprobe_empty_ret, }, 113*988052f4SIan Rogers { "trace_printk_ret", "Attach trace_printk BPF prog to uretprobe on usleep syswide", bench_uprobe_trace_printk_ret,}, 1142df27071SArnaldo Carvalho de Melo { NULL, NULL, NULL }, 1152df27071SArnaldo Carvalho de Melo }; 1162df27071SArnaldo Carvalho de Melo 1174157922aSIngo Molnar struct collection { 118629cc356SHitoshi Mitake const char *name; 119629cc356SHitoshi Mitake const char *summary; 1204157922aSIngo Molnar struct bench *benchmarks; 121629cc356SHitoshi Mitake }; 122629cc356SHitoshi Mitake 1234157922aSIngo Molnar static struct collection collections[] = { 1244157922aSIngo Molnar { "sched", "Scheduler and IPC benchmarks", sched_benchmarks }, 125c2a08203SDavidlohr Bueso { "syscall", "System call benchmarks", syscall_benchmarks }, 1264157922aSIngo Molnar { "mem", "Memory access benchmarks", mem_benchmarks }, 12789fe808aSIngo Molnar #ifdef HAVE_LIBNUMA_SUPPORT 1284157922aSIngo Molnar { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks }, 12979d824e3SPeter Hurley #endif 130a0439711SDavidlohr Bueso {"futex", "Futex stressing benchmarks", futex_benchmarks }, 131ba35fe93SArnaldo Carvalho de Melo #ifdef HAVE_EVENTFD_SUPPORT 132121dd9eaSDavidlohr Bueso {"epoll", "Epoll stressing benchmarks", epoll_benchmarks }, 133121dd9eaSDavidlohr Bueso #endif 1342a4b5166SIan Rogers { "internals", "Perf-internals benchmarks", internals_benchmarks }, 13568a6772fSDmitry Vyukov { "breakpoint", "Breakpoint benchmarks", breakpoint_benchmarks }, 1362df27071SArnaldo Carvalho de Melo { "uprobe", "uprobe benchmarks", uprobe_benchmarks }, 1374157922aSIngo Molnar { "all", "All benchmarks", NULL }, 1384157922aSIngo Molnar { NULL, NULL, NULL } 139629cc356SHitoshi Mitake }; 140629cc356SHitoshi Mitake 1414157922aSIngo Molnar /* Iterate over all benchmark collections: */ 1424157922aSIngo Molnar #define for_each_collection(coll) \ 1434157922aSIngo Molnar for (coll = collections; coll->name; coll++) 1444157922aSIngo Molnar 1454157922aSIngo Molnar /* Iterate over all benchmarks within a collection: */ 1464157922aSIngo Molnar #define for_each_bench(coll, bench) \ 1476eeefccdSPatrick Palka for (bench = coll->benchmarks; bench && bench->name; bench++) 1484157922aSIngo Molnar 1494157922aSIngo Molnar static void dump_benchmarks(struct collection *coll) 150629cc356SHitoshi Mitake { 1514157922aSIngo Molnar struct bench *bench; 152629cc356SHitoshi Mitake 1534157922aSIngo Molnar printf("\n # List of available benchmarks for collection '%s':\n\n", coll->name); 154629cc356SHitoshi Mitake 1554157922aSIngo Molnar for_each_bench(coll, bench) 1564157922aSIngo Molnar printf("%14s: %s\n", bench->name, bench->summary); 157629cc356SHitoshi Mitake 158629cc356SHitoshi Mitake printf("\n"); 159629cc356SHitoshi Mitake } 160629cc356SHitoshi Mitake 161edb7c60eSArnaldo Carvalho de Melo static const char *bench_format_str; 1624157922aSIngo Molnar 1634157922aSIngo Molnar /* Output/formatting style, exported to benchmark modules: */ 164386d7e9eSHitoshi Mitake int bench_format = BENCH_FORMAT_DEFAULT; 165b6f0629aSDavidlohr Bueso unsigned int bench_repeat = 10; /* default number of times to repeat the run */ 166629cc356SHitoshi Mitake 167386d7e9eSHitoshi Mitake static const struct option bench_options[] = { 1687a46a8fdSIngo Molnar OPT_STRING('f', "format", &bench_format_str, "default|simple", "Specify the output formatting style"), 169fc5d836cSDiederik de Haas OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify number of times to repeat the run"), 170386d7e9eSHitoshi Mitake OPT_END() 171386d7e9eSHitoshi Mitake }; 172386d7e9eSHitoshi Mitake 173386d7e9eSHitoshi Mitake static const char * const bench_usage[] = { 1744157922aSIngo Molnar "perf bench [<common options>] <collection> <benchmark> [<options>]", 175386d7e9eSHitoshi Mitake NULL 176386d7e9eSHitoshi Mitake }; 177386d7e9eSHitoshi Mitake 178386d7e9eSHitoshi Mitake static void print_usage(void) 179386d7e9eSHitoshi Mitake { 1804157922aSIngo Molnar struct collection *coll; 181386d7e9eSHitoshi Mitake int i; 182386d7e9eSHitoshi Mitake 183386d7e9eSHitoshi Mitake printf("Usage: \n"); 184386d7e9eSHitoshi Mitake for (i = 0; bench_usage[i]; i++) 185386d7e9eSHitoshi Mitake printf("\t%s\n", bench_usage[i]); 186386d7e9eSHitoshi Mitake printf("\n"); 187386d7e9eSHitoshi Mitake 1884157922aSIngo Molnar printf(" # List of all available benchmark collections:\n\n"); 189629cc356SHitoshi Mitake 1904157922aSIngo Molnar for_each_collection(coll) 1914157922aSIngo Molnar printf("%14s: %s\n", coll->name, coll->summary); 192629cc356SHitoshi Mitake printf("\n"); 193386d7e9eSHitoshi Mitake } 194629cc356SHitoshi Mitake 195edb7c60eSArnaldo Carvalho de Melo static int bench_str2int(const char *str) 196386d7e9eSHitoshi Mitake { 197386d7e9eSHitoshi Mitake if (!str) 198386d7e9eSHitoshi Mitake return BENCH_FORMAT_DEFAULT; 199386d7e9eSHitoshi Mitake 200386d7e9eSHitoshi Mitake if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR)) 201386d7e9eSHitoshi Mitake return BENCH_FORMAT_DEFAULT; 202386d7e9eSHitoshi Mitake else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR)) 203386d7e9eSHitoshi Mitake return BENCH_FORMAT_SIMPLE; 204386d7e9eSHitoshi Mitake 205386d7e9eSHitoshi Mitake return BENCH_FORMAT_UNKNOWN; 206386d7e9eSHitoshi Mitake } 207386d7e9eSHitoshi Mitake 2084157922aSIngo Molnar /* 2094157922aSIngo Molnar * Run a specific benchmark but first rename the running task's ->comm[] 2104157922aSIngo Molnar * to something meaningful: 2114157922aSIngo Molnar */ 2124157922aSIngo Molnar static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn, 213b0ad8ea6SArnaldo Carvalho de Melo int argc, const char **argv) 2142044279dSHitoshi Mitake { 2154157922aSIngo Molnar int size; 2164157922aSIngo Molnar char *name; 2174157922aSIngo Molnar int ret; 2184157922aSIngo Molnar 2194157922aSIngo Molnar size = strlen(coll_name) + 1 + strlen(bench_name) + 1; 2204157922aSIngo Molnar 2214157922aSIngo Molnar name = zalloc(size); 2224157922aSIngo Molnar BUG_ON(!name); 2234157922aSIngo Molnar 2244157922aSIngo Molnar scnprintf(name, size, "%s-%s", coll_name, bench_name); 2254157922aSIngo Molnar 2264157922aSIngo Molnar prctl(PR_SET_NAME, name); 2274157922aSIngo Molnar argv[0] = name; 2284157922aSIngo Molnar 229b0ad8ea6SArnaldo Carvalho de Melo ret = fn(argc, argv); 2304157922aSIngo Molnar 2314157922aSIngo Molnar free(name); 2324157922aSIngo Molnar 2334157922aSIngo Molnar return ret; 2344157922aSIngo Molnar } 2354157922aSIngo Molnar 2364157922aSIngo Molnar static void run_collection(struct collection *coll) 2374157922aSIngo Molnar { 2384157922aSIngo Molnar struct bench *bench; 2392044279dSHitoshi Mitake const char *argv[2]; 2402044279dSHitoshi Mitake 2412044279dSHitoshi Mitake argv[1] = NULL; 2422044279dSHitoshi Mitake /* 2432044279dSHitoshi Mitake * TODO: 2444157922aSIngo Molnar * 2454157922aSIngo Molnar * Preparing preset parameters for 2462044279dSHitoshi Mitake * embedded, ordinary PC, HPC, etc... 2474157922aSIngo Molnar * would be helpful. 2482044279dSHitoshi Mitake */ 2494157922aSIngo Molnar for_each_bench(coll, bench) { 2504157922aSIngo Molnar if (!bench->fn) 2514157922aSIngo Molnar break; 2524157922aSIngo Molnar printf("# Running %s/%s benchmark...\n", coll->name, bench->name); 2532044279dSHitoshi Mitake 2544157922aSIngo Molnar argv[1] = bench->name; 255b0ad8ea6SArnaldo Carvalho de Melo run_bench(coll->name, bench->name, bench->fn, 1, argv); 2562044279dSHitoshi Mitake printf("\n"); 2572044279dSHitoshi Mitake } 2582044279dSHitoshi Mitake } 2592044279dSHitoshi Mitake 2604157922aSIngo Molnar static void run_all_collections(void) 2612044279dSHitoshi Mitake { 2624157922aSIngo Molnar struct collection *coll; 2634157922aSIngo Molnar 2644157922aSIngo Molnar for_each_collection(coll) 2654157922aSIngo Molnar run_collection(coll); 2662044279dSHitoshi Mitake } 2672044279dSHitoshi Mitake 268b0ad8ea6SArnaldo Carvalho de Melo int cmd_bench(int argc, const char **argv) 269386d7e9eSHitoshi Mitake { 2704157922aSIngo Molnar struct collection *coll; 2714157922aSIngo Molnar int ret = 0; 272386d7e9eSHitoshi Mitake 273f0a29c96SSohaib Mohamed /* Unbuffered output */ 274f0a29c96SSohaib Mohamed setvbuf(stdout, NULL, _IONBF, 0); 27516203e9cSArnaldo Carvalho de Melo setlocale(LC_ALL, ""); 276f0a29c96SSohaib Mohamed 277386d7e9eSHitoshi Mitake if (argc < 2) { 2784157922aSIngo Molnar /* No collection specified. */ 279386d7e9eSHitoshi Mitake print_usage(); 280386d7e9eSHitoshi Mitake goto end; 281386d7e9eSHitoshi Mitake } 282386d7e9eSHitoshi Mitake 283386d7e9eSHitoshi Mitake argc = parse_options(argc, argv, bench_options, bench_usage, 284386d7e9eSHitoshi Mitake PARSE_OPT_STOP_AT_NON_OPTION); 285386d7e9eSHitoshi Mitake 286386d7e9eSHitoshi Mitake bench_format = bench_str2int(bench_format_str); 287386d7e9eSHitoshi Mitake if (bench_format == BENCH_FORMAT_UNKNOWN) { 2884157922aSIngo Molnar printf("Unknown format descriptor: '%s'\n", bench_format_str); 289386d7e9eSHitoshi Mitake goto end; 290386d7e9eSHitoshi Mitake } 291386d7e9eSHitoshi Mitake 292b6f0629aSDavidlohr Bueso if (bench_repeat == 0) { 293b6f0629aSDavidlohr Bueso printf("Invalid repeat option: Must specify a positive value\n"); 294b6f0629aSDavidlohr Bueso goto end; 295b6f0629aSDavidlohr Bueso } 296b6f0629aSDavidlohr Bueso 297386d7e9eSHitoshi Mitake if (argc < 1) { 298386d7e9eSHitoshi Mitake print_usage(); 299629cc356SHitoshi Mitake goto end; 300629cc356SHitoshi Mitake } 301629cc356SHitoshi Mitake 3022044279dSHitoshi Mitake if (!strcmp(argv[0], "all")) { 3034157922aSIngo Molnar run_all_collections(); 3042044279dSHitoshi Mitake goto end; 3052044279dSHitoshi Mitake } 3062044279dSHitoshi Mitake 3074157922aSIngo Molnar for_each_collection(coll) { 3084157922aSIngo Molnar struct bench *bench; 3094157922aSIngo Molnar 3104157922aSIngo Molnar if (strcmp(coll->name, argv[0])) 311629cc356SHitoshi Mitake continue; 312629cc356SHitoshi Mitake 313386d7e9eSHitoshi Mitake if (argc < 2) { 3144157922aSIngo Molnar /* No bench specified. */ 3154157922aSIngo Molnar dump_benchmarks(coll); 316629cc356SHitoshi Mitake goto end; 317629cc356SHitoshi Mitake } 318629cc356SHitoshi Mitake 3192044279dSHitoshi Mitake if (!strcmp(argv[1], "all")) { 3204157922aSIngo Molnar run_collection(coll); 3212044279dSHitoshi Mitake goto end; 3222044279dSHitoshi Mitake } 3232044279dSHitoshi Mitake 3244157922aSIngo Molnar for_each_bench(coll, bench) { 3254157922aSIngo Molnar if (strcmp(bench->name, argv[1])) 326629cc356SHitoshi Mitake continue; 327629cc356SHitoshi Mitake 32879e295d4SHitoshi Mitake if (bench_format == BENCH_FORMAT_DEFAULT) 3294157922aSIngo Molnar printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name); 330b0ad8ea6SArnaldo Carvalho de Melo ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1); 331629cc356SHitoshi Mitake goto end; 332629cc356SHitoshi Mitake } 333629cc356SHitoshi Mitake 334386d7e9eSHitoshi Mitake if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 3354157922aSIngo Molnar dump_benchmarks(coll); 336629cc356SHitoshi Mitake goto end; 337629cc356SHitoshi Mitake } 338629cc356SHitoshi Mitake 3394157922aSIngo Molnar printf("Unknown benchmark: '%s' for collection '%s'\n", argv[1], argv[0]); 3404157922aSIngo Molnar ret = 1; 341629cc356SHitoshi Mitake goto end; 342629cc356SHitoshi Mitake } 343629cc356SHitoshi Mitake 3444157922aSIngo Molnar printf("Unknown collection: '%s'\n", argv[0]); 3454157922aSIngo Molnar ret = 1; 346629cc356SHitoshi Mitake 347629cc356SHitoshi Mitake end: 3484157922aSIngo Molnar return ret; 349629cc356SHitoshi Mitake } 350