1 /* 2 * 3 * builtin-bench.c 4 * 5 * General benchmarking subsystem provided by perf 6 * 7 * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 8 * 9 */ 10 11 /* 12 * 13 * Available subsystem list: 14 * sched ... scheduler and IPC mechanism 15 * mem ... memory access performance 16 * 17 */ 18 19 #include "perf.h" 20 #include "util/util.h" 21 #include "util/parse-options.h" 22 #include "builtin.h" 23 #include "bench/bench.h" 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 struct bench_suite { 30 const char *name; 31 const char *summary; 32 int (*fn)(int, const char **, const char *); 33 }; 34 \ 35 /* sentinel: easy for help */ 36 #define suite_all { "all", "Test all benchmark suites", NULL } 37 38 static struct bench_suite sched_suites[] = { 39 { "messaging", 40 "Benchmark for scheduler and IPC mechanisms", 41 bench_sched_messaging }, 42 { "pipe", 43 "Flood of communication over pipe() between two processes", 44 bench_sched_pipe }, 45 suite_all, 46 { NULL, 47 NULL, 48 NULL } 49 }; 50 51 static struct bench_suite mem_suites[] = { 52 { "memcpy", 53 "Simple memory copy in various ways", 54 bench_mem_memcpy }, 55 { "memset", 56 "Simple memory set in various ways", 57 bench_mem_memset }, 58 suite_all, 59 { NULL, 60 NULL, 61 NULL } 62 }; 63 64 struct bench_subsys { 65 const char *name; 66 const char *summary; 67 struct bench_suite *suites; 68 }; 69 70 static struct bench_subsys subsystems[] = { 71 { "sched", 72 "scheduler and IPC mechanism", 73 sched_suites }, 74 { "mem", 75 "memory access performance", 76 mem_suites }, 77 { "all", /* sentinel: easy for help */ 78 "all benchmark subsystem", 79 NULL }, 80 { NULL, 81 NULL, 82 NULL } 83 }; 84 85 static void dump_suites(int subsys_index) 86 { 87 int i; 88 89 printf("# List of available suites for %s...\n\n", 90 subsystems[subsys_index].name); 91 92 for (i = 0; subsystems[subsys_index].suites[i].name; i++) 93 printf("%14s: %s\n", 94 subsystems[subsys_index].suites[i].name, 95 subsystems[subsys_index].suites[i].summary); 96 97 printf("\n"); 98 return; 99 } 100 101 static const char *bench_format_str; 102 int bench_format = BENCH_FORMAT_DEFAULT; 103 104 static const struct option bench_options[] = { 105 OPT_STRING('f', "format", &bench_format_str, "default", 106 "Specify format style"), 107 OPT_END() 108 }; 109 110 static const char * const bench_usage[] = { 111 "perf bench [<common options>] <subsystem> <suite> [<options>]", 112 NULL 113 }; 114 115 static void print_usage(void) 116 { 117 int i; 118 119 printf("Usage: \n"); 120 for (i = 0; bench_usage[i]; i++) 121 printf("\t%s\n", bench_usage[i]); 122 printf("\n"); 123 124 printf("# List of available subsystems...\n\n"); 125 126 for (i = 0; subsystems[i].name; i++) 127 printf("%14s: %s\n", 128 subsystems[i].name, subsystems[i].summary); 129 printf("\n"); 130 } 131 132 static int bench_str2int(const char *str) 133 { 134 if (!str) 135 return BENCH_FORMAT_DEFAULT; 136 137 if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR)) 138 return BENCH_FORMAT_DEFAULT; 139 else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR)) 140 return BENCH_FORMAT_SIMPLE; 141 142 return BENCH_FORMAT_UNKNOWN; 143 } 144 145 static void all_suite(struct bench_subsys *subsys) /* FROM HERE */ 146 { 147 int i; 148 const char *argv[2]; 149 struct bench_suite *suites = subsys->suites; 150 151 argv[1] = NULL; 152 /* 153 * TODO: 154 * preparing preset parameters for 155 * embedded, ordinary PC, HPC, etc... 156 * will be helpful 157 */ 158 for (i = 0; suites[i].fn; i++) { 159 printf("# Running %s/%s benchmark...\n", 160 subsys->name, 161 suites[i].name); 162 163 argv[1] = suites[i].name; 164 suites[i].fn(1, argv, NULL); 165 printf("\n"); 166 } 167 } 168 169 static void all_subsystem(void) 170 { 171 int i; 172 for (i = 0; subsystems[i].suites; i++) 173 all_suite(&subsystems[i]); 174 } 175 176 int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) 177 { 178 int i, j, status = 0; 179 180 if (argc < 2) { 181 /* No subsystem specified. */ 182 print_usage(); 183 goto end; 184 } 185 186 argc = parse_options(argc, argv, bench_options, bench_usage, 187 PARSE_OPT_STOP_AT_NON_OPTION); 188 189 bench_format = bench_str2int(bench_format_str); 190 if (bench_format == BENCH_FORMAT_UNKNOWN) { 191 printf("Unknown format descriptor:%s\n", bench_format_str); 192 goto end; 193 } 194 195 if (argc < 1) { 196 print_usage(); 197 goto end; 198 } 199 200 if (!strcmp(argv[0], "all")) { 201 all_subsystem(); 202 goto end; 203 } 204 205 for (i = 0; subsystems[i].name; i++) { 206 if (strcmp(subsystems[i].name, argv[0])) 207 continue; 208 209 if (argc < 2) { 210 /* No suite specified. */ 211 dump_suites(i); 212 goto end; 213 } 214 215 if (!strcmp(argv[1], "all")) { 216 all_suite(&subsystems[i]); 217 goto end; 218 } 219 220 for (j = 0; subsystems[i].suites[j].name; j++) { 221 if (strcmp(subsystems[i].suites[j].name, argv[1])) 222 continue; 223 224 if (bench_format == BENCH_FORMAT_DEFAULT) 225 printf("# Running %s/%s benchmark...\n", 226 subsystems[i].name, 227 subsystems[i].suites[j].name); 228 status = subsystems[i].suites[j].fn(argc - 1, 229 argv + 1, prefix); 230 goto end; 231 } 232 233 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 234 dump_suites(i); 235 goto end; 236 } 237 238 printf("Unknown suite:%s for %s\n", argv[1], argv[0]); 239 status = 1; 240 goto end; 241 } 242 243 printf("Unknown subsystem:%s\n", argv[0]); 244 status = 1; 245 246 end: 247 return status; 248 } 249