^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * builtin-bench.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * General benchmarking collections provided by perf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Available benchmark collection list:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * sched ... scheduler and IPC performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * syscall ... System call performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * mem ... memory access performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * numa ... NUMA scheduling and MM performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * futex ... Futex performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * epoll ... Event poll performance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <subcmd/parse-options.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "builtin.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "bench/bench.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <sys/prctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) typedef int (*bench_fn_t)(int argc, const char **argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct bench {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) const char *summary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) bench_fn_t fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #ifdef HAVE_LIBNUMA_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static struct bench numa_benchmarks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { "mem", "Benchmark for NUMA workloads", bench_numa },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { "all", "Run all NUMA benchmarks", NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { NULL, NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static struct bench sched_benchmarks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { "all", "Run all scheduler benchmarks", NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { NULL, NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static struct bench syscall_benchmarks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { "basic", "Benchmark for basic getppid(2) calls", bench_syscall_basic },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { "all", "Run all syscall benchmarks", NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { NULL, NULL, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static struct bench mem_benchmarks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { "memcpy", "Benchmark for memcpy() functions", bench_mem_memcpy },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { "memset", "Benchmark for memset() functions", bench_mem_memset },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { "find_bit", "Benchmark for find_bit() functions", bench_mem_find_bit },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { "all", "Run all memory access benchmarks", NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { NULL, NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static struct bench futex_benchmarks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { "hash", "Benchmark for futex hash table", bench_futex_hash },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { "wake", "Benchmark for futex wake calls", bench_futex_wake },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { "wake-parallel", "Benchmark for parallel futex wake calls", bench_futex_wake_parallel },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* pi-futexes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { "all", "Run all futex benchmarks", NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { NULL, NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #ifdef HAVE_EVENTFD_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static struct bench epoll_benchmarks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { "wait", "Benchmark epoll concurrent epoll_waits", bench_epoll_wait },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { "ctl", "Benchmark epoll concurrent epoll_ctls", bench_epoll_ctl },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { "all", "Run all futex benchmarks", NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { NULL, NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #endif // HAVE_EVENTFD_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static struct bench internals_benchmarks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { "synthesize", "Benchmark perf event synthesis", bench_synthesize },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { "kallsyms-parse", "Benchmark kallsyms parsing", bench_kallsyms_parse },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { "inject-build-id", "Benchmark build-id injection", bench_inject_build_id },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { NULL, NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct collection {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) const char *summary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct bench *benchmarks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static struct collection collections[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { "sched", "Scheduler and IPC benchmarks", sched_benchmarks },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { "syscall", "System call benchmarks", syscall_benchmarks },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { "mem", "Memory access benchmarks", mem_benchmarks },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #ifdef HAVE_LIBNUMA_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {"futex", "Futex stressing benchmarks", futex_benchmarks },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #ifdef HAVE_EVENTFD_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {"epoll", "Epoll stressing benchmarks", epoll_benchmarks },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) { "internals", "Perf-internals benchmarks", internals_benchmarks },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { "all", "All benchmarks", NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { NULL, NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Iterate over all benchmark collections: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define for_each_collection(coll) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) for (coll = collections; coll->name; coll++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Iterate over all benchmarks within a collection: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define for_each_bench(coll, bench) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) for (bench = coll->benchmarks; bench && bench->name; bench++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void dump_benchmarks(struct collection *coll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct bench *bench;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) printf("\n # List of available benchmarks for collection '%s':\n\n", coll->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) for_each_bench(coll, bench)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) printf("%14s: %s\n", bench->name, bench->summary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static const char *bench_format_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Output/formatting style, exported to benchmark modules: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int bench_format = BENCH_FORMAT_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned int bench_repeat = 10; /* default number of times to repeat the run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static const struct option bench_options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) OPT_STRING('f', "format", &bench_format_str, "default|simple", "Specify the output formatting style"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) OPT_END()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static const char * const bench_usage[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "perf bench [<common options>] <collection> <benchmark> [<options>]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static void print_usage(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct collection *coll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) printf("Usage: \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) for (i = 0; bench_usage[i]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) printf("\t%s\n", bench_usage[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) printf(" # List of all available benchmark collections:\n\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) for_each_collection(coll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) printf("%14s: %s\n", coll->name, coll->summary);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int bench_str2int(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return BENCH_FORMAT_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return BENCH_FORMAT_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return BENCH_FORMAT_SIMPLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return BENCH_FORMAT_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * Run a specific benchmark but first rename the running task's ->comm[]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * to something meaningful:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) size = strlen(coll_name) + 1 + strlen(bench_name) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) name = zalloc(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) BUG_ON(!name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) scnprintf(name, size, "%s-%s", coll_name, bench_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) prctl(PR_SET_NAME, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) argv[0] = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ret = fn(argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) free(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static void run_collection(struct collection *coll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct bench *bench;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) const char *argv[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) argv[1] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * Preparing preset parameters for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * embedded, ordinary PC, HPC, etc...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * would be helpful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) for_each_bench(coll, bench) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (!bench->fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) printf("# Running %s/%s benchmark...\n", coll->name, bench->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) argv[1] = bench->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) run_bench(coll->name, bench->name, bench->fn, 1, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static void run_all_collections(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct collection *coll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) for_each_collection(coll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) run_collection(coll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) int cmd_bench(int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct collection *coll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (argc < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* No collection specified. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) print_usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) argc = parse_options(argc, argv, bench_options, bench_usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) PARSE_OPT_STOP_AT_NON_OPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) bench_format = bench_str2int(bench_format_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (bench_format == BENCH_FORMAT_UNKNOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) printf("Unknown format descriptor: '%s'\n", bench_format_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (bench_repeat == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) printf("Invalid repeat option: Must specify a positive value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (argc < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) print_usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!strcmp(argv[0], "all")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) run_all_collections();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) for_each_collection(coll) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct bench *bench;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (strcmp(coll->name, argv[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (argc < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* No bench specified. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) dump_benchmarks(coll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (!strcmp(argv[1], "all")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) run_collection(coll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) for_each_bench(coll, bench) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (strcmp(bench->name, argv[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (bench_format == BENCH_FORMAT_DEFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) dump_benchmarks(coll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) printf("Unknown benchmark: '%s' for collection '%s'\n", argv[1], argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) printf("Unknown collection: '%s'\n", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }