1 /* 2 * 3 * builtin-bench.c 4 * 5 * General benchmarking subsystem provided by perf 6 * 7 * Copyright (C) 2009, Hitoshi Mitake <mitake (at) 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 suite (pseudo suite)", 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 suite_all, 56 { NULL, 57 NULL, 58 NULL } 59 }; 60 61 struct bench_subsys { 62 const char *name; 63 const char *summary; 64 struct bench_suite *suites; 65 }; 66 67 static struct bench_subsys subsystems[] = { 68 { "sched", 69 "scheduler and IPC mechanism", 70 sched_suites }, 71 { "mem", 72 "memory access performance", 73 mem_suites }, 74 { "all", /* sentinel: easy for help */ 75 "test all subsystem (pseudo subsystem)", 76 NULL }, 77 { NULL, 78 NULL, 79 NULL } 80 }; 81 82 static void dump_suites(int subsys_index) 83 { 84 int i; 85 86 printf("# List of available suites for %s...\n\n", 87 subsystems[subsys_index].name); 88 89 for (i = 0; subsystems[subsys_index].suites[i].name; i++) 90 printf("%14s: %s\n", 91 subsystems[subsys_index].suites[i].name, 92 subsystems[subsys_index].suites[i].summary); 93 94 printf("\n"); 95 return; 96 } 97 98 static const char *bench_format_str; 99 int bench_format = BENCH_FORMAT_DEFAULT; 100 101 static const struct option bench_options[] = { 102 OPT_STRING('f', "format", &bench_format_str, "default", 103 "Specify format style"), 104 OPT_END() 105 }; 106 107 static const char * const bench_usage[] = { 108 "perf bench [<common options>] <subsystem> <suite> [<options>]", 109 NULL 110 }; 111 112 static void print_usage(void) 113 { 114 int i; 115 116 printf("Usage: \n"); 117 for (i = 0; bench_usage[i]; i++) 118 printf("\t%s\n", bench_usage[i]); 119 printf("\n"); 120 121 printf("# List of available subsystems...\n\n"); 122 123 for (i = 0; subsystems[i].name; i++) 124 printf("%14s: %s\n", 125 subsystems[i].name, subsystems[i].summary); 126 printf("\n"); 127 } 128 129 static int bench_str2int(const char *str) 130 { 131 if (!str) 132 return BENCH_FORMAT_DEFAULT; 133 134 if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR)) 135 return BENCH_FORMAT_DEFAULT; 136 else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR)) 137 return BENCH_FORMAT_SIMPLE; 138 139 return BENCH_FORMAT_UNKNOWN; 140 } 141 142 static void all_suite(struct bench_subsys *subsys) /* FROM HERE */ 143 { 144 int i; 145 const char *argv[2]; 146 struct bench_suite *suites = subsys->suites; 147 148 argv[1] = NULL; 149 /* 150 * TODO: 151 * preparing preset parameters for 152 * embedded, ordinary PC, HPC, etc... 153 * will be helpful 154 */ 155 for (i = 0; suites[i].fn; i++) { 156 printf("# Running %s/%s benchmark...\n", 157 subsys->name, 158 suites[i].name); 159 160 argv[1] = suites[i].name; 161 suites[i].fn(1, argv, NULL); 162 printf("\n"); 163 } 164 } 165 166 static void all_subsystem(void) 167 { 168 int i; 169 for (i = 0; subsystems[i].suites; i++) 170 all_suite(&subsystems[i]); 171 } 172 173 int cmd_bench(int argc, const char **argv, const char *prefix __used) 174 { 175 int i, j, status = 0; 176 177 if (argc < 2) { 178 /* No subsystem specified. */ 179 print_usage(); 180 goto end; 181 } 182 183 argc = parse_options(argc, argv, bench_options, bench_usage, 184 PARSE_OPT_STOP_AT_NON_OPTION); 185 186 bench_format = bench_str2int(bench_format_str); 187 if (bench_format == BENCH_FORMAT_UNKNOWN) { 188 printf("Unknown format descriptor:%s\n", bench_format_str); 189 goto end; 190 } 191 192 if (argc < 1) { 193 print_usage(); 194 goto end; 195 } 196 197 if (!strcmp(argv[0], "all")) { 198 all_subsystem(); 199 goto end; 200 } 201 202 for (i = 0; subsystems[i].name; i++) { 203 if (strcmp(subsystems[i].name, argv[0])) 204 continue; 205 206 if (argc < 2) { 207 /* No suite specified. */ 208 dump_suites(i); 209 goto end; 210 } 211 212 if (!strcmp(argv[1], "all")) { 213 all_suite(&subsystems[i]); 214 goto end; 215 } 216 217 for (j = 0; subsystems[i].suites[j].name; j++) { 218 if (strcmp(subsystems[i].suites[j].name, argv[1])) 219 continue; 220 221 if (bench_format == BENCH_FORMAT_DEFAULT) 222 printf("# Running %s/%s benchmark...\n", 223 subsystems[i].name, 224 subsystems[i].suites[j].name); 225 status = subsystems[i].suites[j].fn(argc - 1, 226 argv + 1, prefix); 227 goto end; 228 } 229 230 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 231 dump_suites(i); 232 goto end; 233 } 234 235 printf("Unknown suite:%s for %s\n", argv[1], argv[0]); 236 status = 1; 237 goto end; 238 } 239 240 printf("Unknown subsystem:%s\n", argv[0]); 241 status = 1; 242 243 end: 244 return status; 245 } 246