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 fflush(stdout); 163 164 argv[1] = suites[i].name; 165 suites[i].fn(1, argv, NULL); 166 printf("\n"); 167 } 168 } 169 170 static void all_subsystem(void) 171 { 172 int i; 173 for (i = 0; subsystems[i].suites; i++) 174 all_suite(&subsystems[i]); 175 } 176 177 int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) 178 { 179 int i, j, status = 0; 180 181 if (argc < 2) { 182 /* No subsystem specified. */ 183 print_usage(); 184 goto end; 185 } 186 187 argc = parse_options(argc, argv, bench_options, bench_usage, 188 PARSE_OPT_STOP_AT_NON_OPTION); 189 190 bench_format = bench_str2int(bench_format_str); 191 if (bench_format == BENCH_FORMAT_UNKNOWN) { 192 printf("Unknown format descriptor:%s\n", bench_format_str); 193 goto end; 194 } 195 196 if (argc < 1) { 197 print_usage(); 198 goto end; 199 } 200 201 if (!strcmp(argv[0], "all")) { 202 all_subsystem(); 203 goto end; 204 } 205 206 for (i = 0; subsystems[i].name; i++) { 207 if (strcmp(subsystems[i].name, argv[0])) 208 continue; 209 210 if (argc < 2) { 211 /* No suite specified. */ 212 dump_suites(i); 213 goto end; 214 } 215 216 if (!strcmp(argv[1], "all")) { 217 all_suite(&subsystems[i]); 218 goto end; 219 } 220 221 for (j = 0; subsystems[i].suites[j].name; j++) { 222 if (strcmp(subsystems[i].suites[j].name, argv[1])) 223 continue; 224 225 if (bench_format == BENCH_FORMAT_DEFAULT) 226 printf("# Running %s/%s benchmark...\n", 227 subsystems[i].name, 228 subsystems[i].suites[j].name); 229 fflush(stdout); 230 status = subsystems[i].suites[j].fn(argc - 1, 231 argv + 1, prefix); 232 goto end; 233 } 234 235 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 236 dump_suites(i); 237 goto end; 238 } 239 240 printf("Unknown suite:%s for %s\n", argv[1], argv[0]); 241 status = 1; 242 goto end; 243 } 244 245 printf("Unknown subsystem:%s\n", argv[0]); 246 status = 1; 247 248 end: 249 return status; 250 } 251