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 14827f3b49SHitoshi Mitake * mem ... memory access performance 154157922aSIngo Molnar * numa ... NUMA scheduling and MM performance 16a0439711SDavidlohr Bueso * futex ... Futex performance 17121dd9eaSDavidlohr Bueso * epoll ... Event poll performance 18629cc356SHitoshi Mitake */ 19629cc356SHitoshi Mitake #include "perf.h" 20629cc356SHitoshi Mitake #include "util/util.h" 214b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 22629cc356SHitoshi Mitake #include "builtin.h" 23629cc356SHitoshi Mitake #include "bench/bench.h" 24629cc356SHitoshi Mitake 25629cc356SHitoshi Mitake #include <stdio.h> 26629cc356SHitoshi Mitake #include <stdlib.h> 27629cc356SHitoshi Mitake #include <string.h> 284157922aSIngo Molnar #include <sys/prctl.h> 29629cc356SHitoshi Mitake 30b0ad8ea6SArnaldo Carvalho de Melo typedef int (*bench_fn_t)(int argc, const char **argv); 314157922aSIngo Molnar 324157922aSIngo Molnar struct bench { 33629cc356SHitoshi Mitake const char *name; 34629cc356SHitoshi Mitake const char *summary; 354157922aSIngo Molnar bench_fn_t fn; 36629cc356SHitoshi Mitake }; 37629cc356SHitoshi Mitake 3889fe808aSIngo Molnar #ifdef HAVE_LIBNUMA_SUPPORT 394157922aSIngo Molnar static struct bench numa_benchmarks[] = { 404157922aSIngo Molnar { "mem", "Benchmark for NUMA workloads", bench_numa }, 41aa254af2SIngo Molnar { "all", "Run all NUMA benchmarks", NULL }, 424157922aSIngo Molnar { NULL, NULL, NULL } 431c13f3c9SIngo Molnar }; 4479d824e3SPeter Hurley #endif 451c13f3c9SIngo Molnar 464157922aSIngo Molnar static struct bench sched_benchmarks[] = { 474157922aSIngo Molnar { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging }, 484157922aSIngo Molnar { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe }, 49aa254af2SIngo Molnar { "all", "Run all scheduler benchmarks", NULL }, 504157922aSIngo Molnar { NULL, NULL, NULL } 51629cc356SHitoshi Mitake }; 52629cc356SHitoshi Mitake 534157922aSIngo Molnar static struct bench mem_benchmarks[] = { 5413b1fdceSIngo Molnar { "memcpy", "Benchmark for memcpy() functions", bench_mem_memcpy }, 5513b1fdceSIngo Molnar { "memset", "Benchmark for memset() functions", bench_mem_memset }, 56aa254af2SIngo Molnar { "all", "Run all memory access benchmarks", NULL }, 574157922aSIngo Molnar { NULL, NULL, NULL } 58827f3b49SHitoshi Mitake }; 59827f3b49SHitoshi Mitake 60a0439711SDavidlohr Bueso static struct bench futex_benchmarks[] = { 61a0439711SDavidlohr Bueso { "hash", "Benchmark for futex hash table", bench_futex_hash }, 6227db7830SDavidlohr Bueso { "wake", "Benchmark for futex wake calls", bench_futex_wake }, 63d65817b4SDavidlohr Bueso { "wake-parallel", "Benchmark for parallel futex wake calls", bench_futex_wake_parallel }, 640fb298cfSDavidlohr Bueso { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue }, 65d2f3f5d2SDavidlohr Bueso /* pi-futexes */ 66d2f3f5d2SDavidlohr Bueso { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi }, 67aa254af2SIngo Molnar { "all", "Run all futex benchmarks", NULL }, 68a0439711SDavidlohr Bueso { NULL, NULL, NULL } 69a0439711SDavidlohr Bueso }; 70a0439711SDavidlohr Bueso 71121dd9eaSDavidlohr Bueso #ifdef HAVE_EVENTFD 72121dd9eaSDavidlohr Bueso static struct bench epoll_benchmarks[] = { 73121dd9eaSDavidlohr Bueso { "wait", "Benchmark epoll concurrent epoll_waits", bench_epoll_wait }, 74*231457ecSDavidlohr Bueso { "ctl", "Benchmark epoll concurrent epoll_ctls", bench_epoll_ctl }, 75121dd9eaSDavidlohr Bueso { "all", "Run all futex benchmarks", NULL }, 76121dd9eaSDavidlohr Bueso { NULL, NULL, NULL } 77121dd9eaSDavidlohr Bueso }; 78121dd9eaSDavidlohr Bueso #endif // HAVE_EVENTFD 79121dd9eaSDavidlohr Bueso 804157922aSIngo Molnar struct collection { 81629cc356SHitoshi Mitake const char *name; 82629cc356SHitoshi Mitake const char *summary; 834157922aSIngo Molnar struct bench *benchmarks; 84629cc356SHitoshi Mitake }; 85629cc356SHitoshi Mitake 864157922aSIngo Molnar static struct collection collections[] = { 874157922aSIngo Molnar { "sched", "Scheduler and IPC benchmarks", sched_benchmarks }, 884157922aSIngo Molnar { "mem", "Memory access benchmarks", mem_benchmarks }, 8989fe808aSIngo Molnar #ifdef HAVE_LIBNUMA_SUPPORT 904157922aSIngo Molnar { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks }, 9179d824e3SPeter Hurley #endif 92a0439711SDavidlohr Bueso {"futex", "Futex stressing benchmarks", futex_benchmarks }, 93121dd9eaSDavidlohr Bueso #ifdef HAVE_EVENTFD 94121dd9eaSDavidlohr Bueso {"epoll", "Epoll stressing benchmarks", epoll_benchmarks }, 95121dd9eaSDavidlohr Bueso #endif 964157922aSIngo Molnar { "all", "All benchmarks", NULL }, 974157922aSIngo Molnar { NULL, NULL, NULL } 98629cc356SHitoshi Mitake }; 99629cc356SHitoshi Mitake 1004157922aSIngo Molnar /* Iterate over all benchmark collections: */ 1014157922aSIngo Molnar #define for_each_collection(coll) \ 1024157922aSIngo Molnar for (coll = collections; coll->name; coll++) 1034157922aSIngo Molnar 1044157922aSIngo Molnar /* Iterate over all benchmarks within a collection: */ 1054157922aSIngo Molnar #define for_each_bench(coll, bench) \ 1066eeefccdSPatrick Palka for (bench = coll->benchmarks; bench && bench->name; bench++) 1074157922aSIngo Molnar 1084157922aSIngo Molnar static void dump_benchmarks(struct collection *coll) 109629cc356SHitoshi Mitake { 1104157922aSIngo Molnar struct bench *bench; 111629cc356SHitoshi Mitake 1124157922aSIngo Molnar printf("\n # List of available benchmarks for collection '%s':\n\n", coll->name); 113629cc356SHitoshi Mitake 1144157922aSIngo Molnar for_each_bench(coll, bench) 1154157922aSIngo Molnar printf("%14s: %s\n", bench->name, bench->summary); 116629cc356SHitoshi Mitake 117629cc356SHitoshi Mitake printf("\n"); 118629cc356SHitoshi Mitake } 119629cc356SHitoshi Mitake 120edb7c60eSArnaldo Carvalho de Melo static const char *bench_format_str; 1214157922aSIngo Molnar 1224157922aSIngo Molnar /* Output/formatting style, exported to benchmark modules: */ 123386d7e9eSHitoshi Mitake int bench_format = BENCH_FORMAT_DEFAULT; 124b6f0629aSDavidlohr Bueso unsigned int bench_repeat = 10; /* default number of times to repeat the run */ 125629cc356SHitoshi Mitake 126386d7e9eSHitoshi Mitake static const struct option bench_options[] = { 1277a46a8fdSIngo Molnar OPT_STRING('f', "format", &bench_format_str, "default|simple", "Specify the output formatting style"), 128b6f0629aSDavidlohr Bueso OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"), 129386d7e9eSHitoshi Mitake OPT_END() 130386d7e9eSHitoshi Mitake }; 131386d7e9eSHitoshi Mitake 132386d7e9eSHitoshi Mitake static const char * const bench_usage[] = { 1334157922aSIngo Molnar "perf bench [<common options>] <collection> <benchmark> [<options>]", 134386d7e9eSHitoshi Mitake NULL 135386d7e9eSHitoshi Mitake }; 136386d7e9eSHitoshi Mitake 137386d7e9eSHitoshi Mitake static void print_usage(void) 138386d7e9eSHitoshi Mitake { 1394157922aSIngo Molnar struct collection *coll; 140386d7e9eSHitoshi Mitake int i; 141386d7e9eSHitoshi Mitake 142386d7e9eSHitoshi Mitake printf("Usage: \n"); 143386d7e9eSHitoshi Mitake for (i = 0; bench_usage[i]; i++) 144386d7e9eSHitoshi Mitake printf("\t%s\n", bench_usage[i]); 145386d7e9eSHitoshi Mitake printf("\n"); 146386d7e9eSHitoshi Mitake 1474157922aSIngo Molnar printf(" # List of all available benchmark collections:\n\n"); 148629cc356SHitoshi Mitake 1494157922aSIngo Molnar for_each_collection(coll) 1504157922aSIngo Molnar printf("%14s: %s\n", coll->name, coll->summary); 151629cc356SHitoshi Mitake printf("\n"); 152386d7e9eSHitoshi Mitake } 153629cc356SHitoshi Mitake 154edb7c60eSArnaldo Carvalho de Melo static int bench_str2int(const char *str) 155386d7e9eSHitoshi Mitake { 156386d7e9eSHitoshi Mitake if (!str) 157386d7e9eSHitoshi Mitake return BENCH_FORMAT_DEFAULT; 158386d7e9eSHitoshi Mitake 159386d7e9eSHitoshi Mitake if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR)) 160386d7e9eSHitoshi Mitake return BENCH_FORMAT_DEFAULT; 161386d7e9eSHitoshi Mitake else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR)) 162386d7e9eSHitoshi Mitake return BENCH_FORMAT_SIMPLE; 163386d7e9eSHitoshi Mitake 164386d7e9eSHitoshi Mitake return BENCH_FORMAT_UNKNOWN; 165386d7e9eSHitoshi Mitake } 166386d7e9eSHitoshi Mitake 1674157922aSIngo Molnar /* 1684157922aSIngo Molnar * Run a specific benchmark but first rename the running task's ->comm[] 1694157922aSIngo Molnar * to something meaningful: 1704157922aSIngo Molnar */ 1714157922aSIngo Molnar static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn, 172b0ad8ea6SArnaldo Carvalho de Melo int argc, const char **argv) 1732044279dSHitoshi Mitake { 1744157922aSIngo Molnar int size; 1754157922aSIngo Molnar char *name; 1764157922aSIngo Molnar int ret; 1774157922aSIngo Molnar 1784157922aSIngo Molnar size = strlen(coll_name) + 1 + strlen(bench_name) + 1; 1794157922aSIngo Molnar 1804157922aSIngo Molnar name = zalloc(size); 1814157922aSIngo Molnar BUG_ON(!name); 1824157922aSIngo Molnar 1834157922aSIngo Molnar scnprintf(name, size, "%s-%s", coll_name, bench_name); 1844157922aSIngo Molnar 1854157922aSIngo Molnar prctl(PR_SET_NAME, name); 1864157922aSIngo Molnar argv[0] = name; 1874157922aSIngo Molnar 188b0ad8ea6SArnaldo Carvalho de Melo ret = fn(argc, argv); 1894157922aSIngo Molnar 1904157922aSIngo Molnar free(name); 1914157922aSIngo Molnar 1924157922aSIngo Molnar return ret; 1934157922aSIngo Molnar } 1944157922aSIngo Molnar 1954157922aSIngo Molnar static void run_collection(struct collection *coll) 1964157922aSIngo Molnar { 1974157922aSIngo Molnar struct bench *bench; 1982044279dSHitoshi Mitake const char *argv[2]; 1992044279dSHitoshi Mitake 2002044279dSHitoshi Mitake argv[1] = NULL; 2012044279dSHitoshi Mitake /* 2022044279dSHitoshi Mitake * TODO: 2034157922aSIngo Molnar * 2044157922aSIngo Molnar * Preparing preset parameters for 2052044279dSHitoshi Mitake * embedded, ordinary PC, HPC, etc... 2064157922aSIngo Molnar * would be helpful. 2072044279dSHitoshi Mitake */ 2084157922aSIngo Molnar for_each_bench(coll, bench) { 2094157922aSIngo Molnar if (!bench->fn) 2104157922aSIngo Molnar break; 2114157922aSIngo Molnar printf("# Running %s/%s benchmark...\n", coll->name, bench->name); 2129b494ea2SNamhyung Kim fflush(stdout); 2132044279dSHitoshi Mitake 2144157922aSIngo Molnar argv[1] = bench->name; 215b0ad8ea6SArnaldo Carvalho de Melo run_bench(coll->name, bench->name, bench->fn, 1, argv); 2162044279dSHitoshi Mitake printf("\n"); 2172044279dSHitoshi Mitake } 2182044279dSHitoshi Mitake } 2192044279dSHitoshi Mitake 2204157922aSIngo Molnar static void run_all_collections(void) 2212044279dSHitoshi Mitake { 2224157922aSIngo Molnar struct collection *coll; 2234157922aSIngo Molnar 2244157922aSIngo Molnar for_each_collection(coll) 2254157922aSIngo Molnar run_collection(coll); 2262044279dSHitoshi Mitake } 2272044279dSHitoshi Mitake 228b0ad8ea6SArnaldo Carvalho de Melo int cmd_bench(int argc, const char **argv) 229386d7e9eSHitoshi Mitake { 2304157922aSIngo Molnar struct collection *coll; 2314157922aSIngo Molnar int ret = 0; 232386d7e9eSHitoshi Mitake 233386d7e9eSHitoshi Mitake if (argc < 2) { 2344157922aSIngo Molnar /* No collection specified. */ 235386d7e9eSHitoshi Mitake print_usage(); 236386d7e9eSHitoshi Mitake goto end; 237386d7e9eSHitoshi Mitake } 238386d7e9eSHitoshi Mitake 239386d7e9eSHitoshi Mitake argc = parse_options(argc, argv, bench_options, bench_usage, 240386d7e9eSHitoshi Mitake PARSE_OPT_STOP_AT_NON_OPTION); 241386d7e9eSHitoshi Mitake 242386d7e9eSHitoshi Mitake bench_format = bench_str2int(bench_format_str); 243386d7e9eSHitoshi Mitake if (bench_format == BENCH_FORMAT_UNKNOWN) { 2444157922aSIngo Molnar printf("Unknown format descriptor: '%s'\n", bench_format_str); 245386d7e9eSHitoshi Mitake goto end; 246386d7e9eSHitoshi Mitake } 247386d7e9eSHitoshi Mitake 248b6f0629aSDavidlohr Bueso if (bench_repeat == 0) { 249b6f0629aSDavidlohr Bueso printf("Invalid repeat option: Must specify a positive value\n"); 250b6f0629aSDavidlohr Bueso goto end; 251b6f0629aSDavidlohr Bueso } 252b6f0629aSDavidlohr Bueso 253386d7e9eSHitoshi Mitake if (argc < 1) { 254386d7e9eSHitoshi Mitake print_usage(); 255629cc356SHitoshi Mitake goto end; 256629cc356SHitoshi Mitake } 257629cc356SHitoshi Mitake 2582044279dSHitoshi Mitake if (!strcmp(argv[0], "all")) { 2594157922aSIngo Molnar run_all_collections(); 2602044279dSHitoshi Mitake goto end; 2612044279dSHitoshi Mitake } 2622044279dSHitoshi Mitake 2634157922aSIngo Molnar for_each_collection(coll) { 2644157922aSIngo Molnar struct bench *bench; 2654157922aSIngo Molnar 2664157922aSIngo Molnar if (strcmp(coll->name, argv[0])) 267629cc356SHitoshi Mitake continue; 268629cc356SHitoshi Mitake 269386d7e9eSHitoshi Mitake if (argc < 2) { 2704157922aSIngo Molnar /* No bench specified. */ 2714157922aSIngo Molnar dump_benchmarks(coll); 272629cc356SHitoshi Mitake goto end; 273629cc356SHitoshi Mitake } 274629cc356SHitoshi Mitake 2752044279dSHitoshi Mitake if (!strcmp(argv[1], "all")) { 2764157922aSIngo Molnar run_collection(coll); 2772044279dSHitoshi Mitake goto end; 2782044279dSHitoshi Mitake } 2792044279dSHitoshi Mitake 2804157922aSIngo Molnar for_each_bench(coll, bench) { 2814157922aSIngo Molnar if (strcmp(bench->name, argv[1])) 282629cc356SHitoshi Mitake continue; 283629cc356SHitoshi Mitake 28479e295d4SHitoshi Mitake if (bench_format == BENCH_FORMAT_DEFAULT) 2854157922aSIngo Molnar printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name); 2869b494ea2SNamhyung Kim fflush(stdout); 287b0ad8ea6SArnaldo Carvalho de Melo ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1); 288629cc356SHitoshi Mitake goto end; 289629cc356SHitoshi Mitake } 290629cc356SHitoshi Mitake 291386d7e9eSHitoshi Mitake if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 2924157922aSIngo Molnar dump_benchmarks(coll); 293629cc356SHitoshi Mitake goto end; 294629cc356SHitoshi Mitake } 295629cc356SHitoshi Mitake 2964157922aSIngo Molnar printf("Unknown benchmark: '%s' for collection '%s'\n", argv[1], argv[0]); 2974157922aSIngo Molnar ret = 1; 298629cc356SHitoshi Mitake goto end; 299629cc356SHitoshi Mitake } 300629cc356SHitoshi Mitake 3014157922aSIngo Molnar printf("Unknown collection: '%s'\n", argv[0]); 3024157922aSIngo Molnar ret = 1; 303629cc356SHitoshi Mitake 304629cc356SHitoshi Mitake end: 3054157922aSIngo Molnar return ret; 306629cc356SHitoshi Mitake } 307