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 24*16203e9cSArnaldo 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 }, 50aa254af2SIngo Molnar { "all", "Run all scheduler benchmarks", NULL }, 514157922aSIngo Molnar { NULL, NULL, NULL } 52629cc356SHitoshi Mitake }; 53629cc356SHitoshi Mitake 54c2a08203SDavidlohr Bueso static struct bench syscall_benchmarks[] = { 55c2a08203SDavidlohr Bueso { "basic", "Benchmark for basic getppid(2) calls", bench_syscall_basic }, 56391f84e5STiezhu Yang { "getpgid", "Benchmark for getpgid(2) calls", bench_syscall_getpgid }, 57ece7f7c0STiezhu Yang { "fork", "Benchmark for fork(2) calls", bench_syscall_fork }, 58540f8b56STiezhu Yang { "execve", "Benchmark for execve(2) calls", bench_syscall_execve }, 59c2a08203SDavidlohr Bueso { "all", "Run all syscall benchmarks", NULL }, 60c2a08203SDavidlohr Bueso { NULL, NULL, NULL }, 61c2a08203SDavidlohr Bueso }; 62c2a08203SDavidlohr Bueso 634157922aSIngo Molnar static struct bench mem_benchmarks[] = { 6413b1fdceSIngo Molnar { "memcpy", "Benchmark for memcpy() functions", bench_mem_memcpy }, 6513b1fdceSIngo Molnar { "memset", "Benchmark for memset() functions", bench_mem_memset }, 667c43b0c1SIan Rogers { "find_bit", "Benchmark for find_bit() functions", bench_mem_find_bit }, 67aa254af2SIngo Molnar { "all", "Run all memory access benchmarks", NULL }, 684157922aSIngo Molnar { NULL, NULL, NULL } 69827f3b49SHitoshi Mitake }; 70827f3b49SHitoshi Mitake 71a0439711SDavidlohr Bueso static struct bench futex_benchmarks[] = { 72a0439711SDavidlohr Bueso { "hash", "Benchmark for futex hash table", bench_futex_hash }, 7327db7830SDavidlohr Bueso { "wake", "Benchmark for futex wake calls", bench_futex_wake }, 74d65817b4SDavidlohr Bueso { "wake-parallel", "Benchmark for parallel futex wake calls", bench_futex_wake_parallel }, 750fb298cfSDavidlohr Bueso { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue }, 76d2f3f5d2SDavidlohr Bueso /* pi-futexes */ 77d2f3f5d2SDavidlohr Bueso { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi }, 78aa254af2SIngo Molnar { "all", "Run all futex benchmarks", NULL }, 79a0439711SDavidlohr Bueso { NULL, NULL, NULL } 80a0439711SDavidlohr Bueso }; 81a0439711SDavidlohr Bueso 82ba35fe93SArnaldo Carvalho de Melo #ifdef HAVE_EVENTFD_SUPPORT 83121dd9eaSDavidlohr Bueso static struct bench epoll_benchmarks[] = { 84121dd9eaSDavidlohr Bueso { "wait", "Benchmark epoll concurrent epoll_waits", bench_epoll_wait }, 85231457ecSDavidlohr Bueso { "ctl", "Benchmark epoll concurrent epoll_ctls", bench_epoll_ctl }, 86121dd9eaSDavidlohr Bueso { "all", "Run all futex benchmarks", NULL }, 87121dd9eaSDavidlohr Bueso { NULL, NULL, NULL } 88121dd9eaSDavidlohr Bueso }; 89ba35fe93SArnaldo Carvalho de Melo #endif // HAVE_EVENTFD_SUPPORT 90121dd9eaSDavidlohr Bueso 912a4b5166SIan Rogers static struct bench internals_benchmarks[] = { 922a4b5166SIan Rogers { "synthesize", "Benchmark perf event synthesis", bench_synthesize }, 9351876bd4SIan Rogers { "kallsyms-parse", "Benchmark kallsyms parsing", bench_kallsyms_parse }, 940bf02a0dSNamhyung Kim { "inject-build-id", "Benchmark build-id injection", bench_inject_build_id }, 954241eabfSRiccardo Mancini { "evlist-open-close", "Benchmark evlist open and close", bench_evlist_open_close }, 96f6a7bbbfSNamhyung Kim { "pmu-scan", "Benchmark sysfs PMU info scanning", bench_pmu_scan }, 972a4b5166SIan Rogers { NULL, NULL, NULL } 982a4b5166SIan Rogers }; 992a4b5166SIan Rogers 10068a6772fSDmitry Vyukov static struct bench breakpoint_benchmarks[] = { 10168a6772fSDmitry Vyukov { "thread", "Benchmark thread start/finish with breakpoints", bench_breakpoint_thread}, 10268a6772fSDmitry Vyukov { "enable", "Benchmark breakpoint enable/disable", bench_breakpoint_enable}, 10368a6772fSDmitry Vyukov { "all", "Run all breakpoint benchmarks", NULL}, 10468a6772fSDmitry Vyukov { NULL, NULL, NULL }, 10568a6772fSDmitry Vyukov }; 10668a6772fSDmitry Vyukov 1074157922aSIngo Molnar struct collection { 108629cc356SHitoshi Mitake const char *name; 109629cc356SHitoshi Mitake const char *summary; 1104157922aSIngo Molnar struct bench *benchmarks; 111629cc356SHitoshi Mitake }; 112629cc356SHitoshi Mitake 1134157922aSIngo Molnar static struct collection collections[] = { 1144157922aSIngo Molnar { "sched", "Scheduler and IPC benchmarks", sched_benchmarks }, 115c2a08203SDavidlohr Bueso { "syscall", "System call benchmarks", syscall_benchmarks }, 1164157922aSIngo Molnar { "mem", "Memory access benchmarks", mem_benchmarks }, 11789fe808aSIngo Molnar #ifdef HAVE_LIBNUMA_SUPPORT 1184157922aSIngo Molnar { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks }, 11979d824e3SPeter Hurley #endif 120a0439711SDavidlohr Bueso {"futex", "Futex stressing benchmarks", futex_benchmarks }, 121ba35fe93SArnaldo Carvalho de Melo #ifdef HAVE_EVENTFD_SUPPORT 122121dd9eaSDavidlohr Bueso {"epoll", "Epoll stressing benchmarks", epoll_benchmarks }, 123121dd9eaSDavidlohr Bueso #endif 1242a4b5166SIan Rogers { "internals", "Perf-internals benchmarks", internals_benchmarks }, 12568a6772fSDmitry Vyukov { "breakpoint", "Breakpoint benchmarks", breakpoint_benchmarks }, 1264157922aSIngo Molnar { "all", "All benchmarks", NULL }, 1274157922aSIngo Molnar { NULL, NULL, NULL } 128629cc356SHitoshi Mitake }; 129629cc356SHitoshi Mitake 1304157922aSIngo Molnar /* Iterate over all benchmark collections: */ 1314157922aSIngo Molnar #define for_each_collection(coll) \ 1324157922aSIngo Molnar for (coll = collections; coll->name; coll++) 1334157922aSIngo Molnar 1344157922aSIngo Molnar /* Iterate over all benchmarks within a collection: */ 1354157922aSIngo Molnar #define for_each_bench(coll, bench) \ 1366eeefccdSPatrick Palka for (bench = coll->benchmarks; bench && bench->name; bench++) 1374157922aSIngo Molnar 1384157922aSIngo Molnar static void dump_benchmarks(struct collection *coll) 139629cc356SHitoshi Mitake { 1404157922aSIngo Molnar struct bench *bench; 141629cc356SHitoshi Mitake 1424157922aSIngo Molnar printf("\n # List of available benchmarks for collection '%s':\n\n", coll->name); 143629cc356SHitoshi Mitake 1444157922aSIngo Molnar for_each_bench(coll, bench) 1454157922aSIngo Molnar printf("%14s: %s\n", bench->name, bench->summary); 146629cc356SHitoshi Mitake 147629cc356SHitoshi Mitake printf("\n"); 148629cc356SHitoshi Mitake } 149629cc356SHitoshi Mitake 150edb7c60eSArnaldo Carvalho de Melo static const char *bench_format_str; 1514157922aSIngo Molnar 1524157922aSIngo Molnar /* Output/formatting style, exported to benchmark modules: */ 153386d7e9eSHitoshi Mitake int bench_format = BENCH_FORMAT_DEFAULT; 154b6f0629aSDavidlohr Bueso unsigned int bench_repeat = 10; /* default number of times to repeat the run */ 155629cc356SHitoshi Mitake 156386d7e9eSHitoshi Mitake static const struct option bench_options[] = { 1577a46a8fdSIngo Molnar OPT_STRING('f', "format", &bench_format_str, "default|simple", "Specify the output formatting style"), 158fc5d836cSDiederik de Haas OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify number of times to repeat the run"), 159386d7e9eSHitoshi Mitake OPT_END() 160386d7e9eSHitoshi Mitake }; 161386d7e9eSHitoshi Mitake 162386d7e9eSHitoshi Mitake static const char * const bench_usage[] = { 1634157922aSIngo Molnar "perf bench [<common options>] <collection> <benchmark> [<options>]", 164386d7e9eSHitoshi Mitake NULL 165386d7e9eSHitoshi Mitake }; 166386d7e9eSHitoshi Mitake 167386d7e9eSHitoshi Mitake static void print_usage(void) 168386d7e9eSHitoshi Mitake { 1694157922aSIngo Molnar struct collection *coll; 170386d7e9eSHitoshi Mitake int i; 171386d7e9eSHitoshi Mitake 172386d7e9eSHitoshi Mitake printf("Usage: \n"); 173386d7e9eSHitoshi Mitake for (i = 0; bench_usage[i]; i++) 174386d7e9eSHitoshi Mitake printf("\t%s\n", bench_usage[i]); 175386d7e9eSHitoshi Mitake printf("\n"); 176386d7e9eSHitoshi Mitake 1774157922aSIngo Molnar printf(" # List of all available benchmark collections:\n\n"); 178629cc356SHitoshi Mitake 1794157922aSIngo Molnar for_each_collection(coll) 1804157922aSIngo Molnar printf("%14s: %s\n", coll->name, coll->summary); 181629cc356SHitoshi Mitake printf("\n"); 182386d7e9eSHitoshi Mitake } 183629cc356SHitoshi Mitake 184edb7c60eSArnaldo Carvalho de Melo static int bench_str2int(const char *str) 185386d7e9eSHitoshi Mitake { 186386d7e9eSHitoshi Mitake if (!str) 187386d7e9eSHitoshi Mitake return BENCH_FORMAT_DEFAULT; 188386d7e9eSHitoshi Mitake 189386d7e9eSHitoshi Mitake if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR)) 190386d7e9eSHitoshi Mitake return BENCH_FORMAT_DEFAULT; 191386d7e9eSHitoshi Mitake else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR)) 192386d7e9eSHitoshi Mitake return BENCH_FORMAT_SIMPLE; 193386d7e9eSHitoshi Mitake 194386d7e9eSHitoshi Mitake return BENCH_FORMAT_UNKNOWN; 195386d7e9eSHitoshi Mitake } 196386d7e9eSHitoshi Mitake 1974157922aSIngo Molnar /* 1984157922aSIngo Molnar * Run a specific benchmark but first rename the running task's ->comm[] 1994157922aSIngo Molnar * to something meaningful: 2004157922aSIngo Molnar */ 2014157922aSIngo Molnar static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn, 202b0ad8ea6SArnaldo Carvalho de Melo int argc, const char **argv) 2032044279dSHitoshi Mitake { 2044157922aSIngo Molnar int size; 2054157922aSIngo Molnar char *name; 2064157922aSIngo Molnar int ret; 2074157922aSIngo Molnar 2084157922aSIngo Molnar size = strlen(coll_name) + 1 + strlen(bench_name) + 1; 2094157922aSIngo Molnar 2104157922aSIngo Molnar name = zalloc(size); 2114157922aSIngo Molnar BUG_ON(!name); 2124157922aSIngo Molnar 2134157922aSIngo Molnar scnprintf(name, size, "%s-%s", coll_name, bench_name); 2144157922aSIngo Molnar 2154157922aSIngo Molnar prctl(PR_SET_NAME, name); 2164157922aSIngo Molnar argv[0] = name; 2174157922aSIngo Molnar 218b0ad8ea6SArnaldo Carvalho de Melo ret = fn(argc, argv); 2194157922aSIngo Molnar 2204157922aSIngo Molnar free(name); 2214157922aSIngo Molnar 2224157922aSIngo Molnar return ret; 2234157922aSIngo Molnar } 2244157922aSIngo Molnar 2254157922aSIngo Molnar static void run_collection(struct collection *coll) 2264157922aSIngo Molnar { 2274157922aSIngo Molnar struct bench *bench; 2282044279dSHitoshi Mitake const char *argv[2]; 2292044279dSHitoshi Mitake 2302044279dSHitoshi Mitake argv[1] = NULL; 2312044279dSHitoshi Mitake /* 2322044279dSHitoshi Mitake * TODO: 2334157922aSIngo Molnar * 2344157922aSIngo Molnar * Preparing preset parameters for 2352044279dSHitoshi Mitake * embedded, ordinary PC, HPC, etc... 2364157922aSIngo Molnar * would be helpful. 2372044279dSHitoshi Mitake */ 2384157922aSIngo Molnar for_each_bench(coll, bench) { 2394157922aSIngo Molnar if (!bench->fn) 2404157922aSIngo Molnar break; 2414157922aSIngo Molnar printf("# Running %s/%s benchmark...\n", coll->name, bench->name); 2422044279dSHitoshi Mitake 2434157922aSIngo Molnar argv[1] = bench->name; 244b0ad8ea6SArnaldo Carvalho de Melo run_bench(coll->name, bench->name, bench->fn, 1, argv); 2452044279dSHitoshi Mitake printf("\n"); 2462044279dSHitoshi Mitake } 2472044279dSHitoshi Mitake } 2482044279dSHitoshi Mitake 2494157922aSIngo Molnar static void run_all_collections(void) 2502044279dSHitoshi Mitake { 2514157922aSIngo Molnar struct collection *coll; 2524157922aSIngo Molnar 2534157922aSIngo Molnar for_each_collection(coll) 2544157922aSIngo Molnar run_collection(coll); 2552044279dSHitoshi Mitake } 2562044279dSHitoshi Mitake 257b0ad8ea6SArnaldo Carvalho de Melo int cmd_bench(int argc, const char **argv) 258386d7e9eSHitoshi Mitake { 2594157922aSIngo Molnar struct collection *coll; 2604157922aSIngo Molnar int ret = 0; 261386d7e9eSHitoshi Mitake 262f0a29c96SSohaib Mohamed /* Unbuffered output */ 263f0a29c96SSohaib Mohamed setvbuf(stdout, NULL, _IONBF, 0); 264*16203e9cSArnaldo Carvalho de Melo setlocale(LC_ALL, ""); 265f0a29c96SSohaib Mohamed 266386d7e9eSHitoshi Mitake if (argc < 2) { 2674157922aSIngo Molnar /* No collection specified. */ 268386d7e9eSHitoshi Mitake print_usage(); 269386d7e9eSHitoshi Mitake goto end; 270386d7e9eSHitoshi Mitake } 271386d7e9eSHitoshi Mitake 272386d7e9eSHitoshi Mitake argc = parse_options(argc, argv, bench_options, bench_usage, 273386d7e9eSHitoshi Mitake PARSE_OPT_STOP_AT_NON_OPTION); 274386d7e9eSHitoshi Mitake 275386d7e9eSHitoshi Mitake bench_format = bench_str2int(bench_format_str); 276386d7e9eSHitoshi Mitake if (bench_format == BENCH_FORMAT_UNKNOWN) { 2774157922aSIngo Molnar printf("Unknown format descriptor: '%s'\n", bench_format_str); 278386d7e9eSHitoshi Mitake goto end; 279386d7e9eSHitoshi Mitake } 280386d7e9eSHitoshi Mitake 281b6f0629aSDavidlohr Bueso if (bench_repeat == 0) { 282b6f0629aSDavidlohr Bueso printf("Invalid repeat option: Must specify a positive value\n"); 283b6f0629aSDavidlohr Bueso goto end; 284b6f0629aSDavidlohr Bueso } 285b6f0629aSDavidlohr Bueso 286386d7e9eSHitoshi Mitake if (argc < 1) { 287386d7e9eSHitoshi Mitake print_usage(); 288629cc356SHitoshi Mitake goto end; 289629cc356SHitoshi Mitake } 290629cc356SHitoshi Mitake 2912044279dSHitoshi Mitake if (!strcmp(argv[0], "all")) { 2924157922aSIngo Molnar run_all_collections(); 2932044279dSHitoshi Mitake goto end; 2942044279dSHitoshi Mitake } 2952044279dSHitoshi Mitake 2964157922aSIngo Molnar for_each_collection(coll) { 2974157922aSIngo Molnar struct bench *bench; 2984157922aSIngo Molnar 2994157922aSIngo Molnar if (strcmp(coll->name, argv[0])) 300629cc356SHitoshi Mitake continue; 301629cc356SHitoshi Mitake 302386d7e9eSHitoshi Mitake if (argc < 2) { 3034157922aSIngo Molnar /* No bench specified. */ 3044157922aSIngo Molnar dump_benchmarks(coll); 305629cc356SHitoshi Mitake goto end; 306629cc356SHitoshi Mitake } 307629cc356SHitoshi Mitake 3082044279dSHitoshi Mitake if (!strcmp(argv[1], "all")) { 3094157922aSIngo Molnar run_collection(coll); 3102044279dSHitoshi Mitake goto end; 3112044279dSHitoshi Mitake } 3122044279dSHitoshi Mitake 3134157922aSIngo Molnar for_each_bench(coll, bench) { 3144157922aSIngo Molnar if (strcmp(bench->name, argv[1])) 315629cc356SHitoshi Mitake continue; 316629cc356SHitoshi Mitake 31779e295d4SHitoshi Mitake if (bench_format == BENCH_FORMAT_DEFAULT) 3184157922aSIngo Molnar printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name); 319b0ad8ea6SArnaldo Carvalho de Melo ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1); 320629cc356SHitoshi Mitake goto end; 321629cc356SHitoshi Mitake } 322629cc356SHitoshi Mitake 323386d7e9eSHitoshi Mitake if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 3244157922aSIngo Molnar dump_benchmarks(coll); 325629cc356SHitoshi Mitake goto end; 326629cc356SHitoshi Mitake } 327629cc356SHitoshi Mitake 3284157922aSIngo Molnar printf("Unknown benchmark: '%s' for collection '%s'\n", argv[1], argv[0]); 3294157922aSIngo Molnar ret = 1; 330629cc356SHitoshi Mitake goto end; 331629cc356SHitoshi Mitake } 332629cc356SHitoshi Mitake 3334157922aSIngo Molnar printf("Unknown collection: '%s'\n", argv[0]); 3344157922aSIngo Molnar ret = 1; 335629cc356SHitoshi Mitake 336629cc356SHitoshi Mitake end: 3374157922aSIngo Molnar return ret; 338629cc356SHitoshi Mitake } 339