aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-bench.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-bench.c')
-rw-r--r--tools/perf/builtin-bench.c245
1 files changed, 125 insertions, 120 deletions
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 77298bf892b8..e47f90cc7b98 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -1,21 +1,18 @@
1/* 1/*
2 *
3 * builtin-bench.c 2 * builtin-bench.c
4 * 3 *
5 * General benchmarking subsystem provided by perf 4 * General benchmarking collections provided by perf
6 * 5 *
7 * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 6 * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
8 *
9 */ 7 */
10 8
11/* 9/*
10 * Available benchmark collection list:
12 * 11 *
13 * Available subsystem list: 12 * sched ... scheduler and IPC performance
14 * sched ... scheduler and IPC mechanism
15 * mem ... memory access performance 13 * mem ... memory access performance
16 * 14 * numa ... NUMA scheduling and MM performance
17 */ 15 */
18
19#include "perf.h" 16#include "perf.h"
20#include "util/util.h" 17#include "util/util.h"
21#include "util/parse-options.h" 18#include "util/parse-options.h"
@@ -25,112 +22,92 @@
25#include <stdio.h> 22#include <stdio.h>
26#include <stdlib.h> 23#include <stdlib.h>
27#include <string.h> 24#include <string.h>
25#include <sys/prctl.h>
28 26
29struct bench_suite { 27typedef int (*bench_fn_t)(int argc, const char **argv, const char *prefix);
30 const char *name; 28
31 const char *summary; 29struct bench {
32 int (*fn)(int, const char **, const char *); 30 const char *name;
31 const char *summary;
32 bench_fn_t fn;
33}; 33};
34 \ 34
35/* sentinel: easy for help */ 35#ifdef HAVE_LIBNUMA_SUPPORT
36#define suite_all { "all", "Test all benchmark suites", NULL } 36static struct bench numa_benchmarks[] = {
37 37 { "mem", "Benchmark for NUMA workloads", bench_numa },
38#ifdef LIBNUMA_SUPPORT 38 { "all", "Test all NUMA benchmarks", NULL },
39static struct bench_suite numa_suites[] = { 39 { NULL, NULL, NULL }
40 { "mem",
41 "Benchmark for NUMA workloads",
42 bench_numa },
43 suite_all,
44 { NULL,
45 NULL,
46 NULL }
47}; 40};
48#endif 41#endif
49 42
50static struct bench_suite sched_suites[] = { 43static struct bench sched_benchmarks[] = {
51 { "messaging", 44 { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging },
52 "Benchmark for scheduler and IPC mechanisms", 45 { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe },
53 bench_sched_messaging }, 46 { "all", "Test all scheduler benchmarks", NULL },
54 { "pipe", 47 { NULL, NULL, NULL }
55 "Flood of communication over pipe() between two processes",
56 bench_sched_pipe },
57 suite_all,
58 { NULL,
59 NULL,
60 NULL }
61}; 48};
62 49
63static struct bench_suite mem_suites[] = { 50static struct bench mem_benchmarks[] = {
64 { "memcpy", 51 { "memcpy", "Benchmark for memcpy()", bench_mem_memcpy },
65 "Simple memory copy in various ways", 52 { "memset", "Benchmark for memset() tests", bench_mem_memset },
66 bench_mem_memcpy }, 53 { "all", "Test all memory benchmarks", NULL },
67 { "memset", 54 { NULL, NULL, NULL }
68 "Simple memory set in various ways",
69 bench_mem_memset },
70 suite_all,
71 { NULL,
72 NULL,
73 NULL }
74}; 55};
75 56
76struct bench_subsys { 57struct collection {
77 const char *name; 58 const char *name;
78 const char *summary; 59 const char *summary;
79 struct bench_suite *suites; 60 struct bench *benchmarks;
80}; 61};
81 62
82static struct bench_subsys subsystems[] = { 63static struct collection collections[] = {
83#ifdef LIBNUMA_SUPPORT 64 { "sched", "Scheduler and IPC benchmarks", sched_benchmarks },
84 { "numa", 65 { "mem", "Memory access benchmarks", mem_benchmarks },
85 "NUMA scheduling and MM behavior", 66#ifdef HAVE_LIBNUMA_SUPPORT
86 numa_suites }, 67 { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks },
87#endif 68#endif
88 { "sched", 69 { "all", "All benchmarks", NULL },
89 "scheduler and IPC mechanism", 70 { NULL, NULL, NULL }
90 sched_suites },
91 { "mem",
92 "memory access performance",
93 mem_suites },
94 { "all", /* sentinel: easy for help */
95 "all benchmark subsystem",
96 NULL },
97 { NULL,
98 NULL,
99 NULL }
100}; 71};
101 72
102static void dump_suites(int subsys_index) 73/* Iterate over all benchmark collections: */
74#define for_each_collection(coll) \
75 for (coll = collections; coll->name; coll++)
76
77/* Iterate over all benchmarks within a collection: */
78#define for_each_bench(coll, bench) \
79 for (bench = coll->benchmarks; bench->name; bench++)
80
81static void dump_benchmarks(struct collection *coll)
103{ 82{
104 int i; 83 struct bench *bench;
105 84
106 printf("# List of available suites for %s...\n\n", 85 printf("\n # List of available benchmarks for collection '%s':\n\n", coll->name);
107 subsystems[subsys_index].name);
108 86
109 for (i = 0; subsystems[subsys_index].suites[i].name; i++) 87 for_each_bench(coll, bench)
110 printf("%14s: %s\n", 88 printf("%14s: %s\n", bench->name, bench->summary);
111 subsystems[subsys_index].suites[i].name,
112 subsystems[subsys_index].suites[i].summary);
113 89
114 printf("\n"); 90 printf("\n");
115 return;
116} 91}
117 92
118static const char *bench_format_str; 93static const char *bench_format_str;
94
95/* Output/formatting style, exported to benchmark modules: */
119int bench_format = BENCH_FORMAT_DEFAULT; 96int bench_format = BENCH_FORMAT_DEFAULT;
120 97
121static const struct option bench_options[] = { 98static const struct option bench_options[] = {
122 OPT_STRING('f', "format", &bench_format_str, "default", 99 OPT_STRING('f', "format", &bench_format_str, "default", "Specify format style"),
123 "Specify format style"),
124 OPT_END() 100 OPT_END()
125}; 101};
126 102
127static const char * const bench_usage[] = { 103static const char * const bench_usage[] = {
128 "perf bench [<common options>] <subsystem> <suite> [<options>]", 104 "perf bench [<common options>] <collection> <benchmark> [<options>]",
129 NULL 105 NULL
130}; 106};
131 107
132static void print_usage(void) 108static void print_usage(void)
133{ 109{
110 struct collection *coll;
134 int i; 111 int i;
135 112
136 printf("Usage: \n"); 113 printf("Usage: \n");
@@ -138,11 +115,10 @@ static void print_usage(void)
138 printf("\t%s\n", bench_usage[i]); 115 printf("\t%s\n", bench_usage[i]);
139 printf("\n"); 116 printf("\n");
140 117
141 printf("# List of available subsystems...\n\n"); 118 printf(" # List of all available benchmark collections:\n\n");
142 119
143 for (i = 0; subsystems[i].name; i++) 120 for_each_collection(coll)
144 printf("%14s: %s\n", 121 printf("%14s: %s\n", coll->name, coll->summary);
145 subsystems[i].name, subsystems[i].summary);
146 printf("\n"); 122 printf("\n");
147} 123}
148 124
@@ -159,44 +135,74 @@ static int bench_str2int(const char *str)
159 return BENCH_FORMAT_UNKNOWN; 135 return BENCH_FORMAT_UNKNOWN;
160} 136}
161 137
162static void all_suite(struct bench_subsys *subsys) /* FROM HERE */ 138/*
139 * Run a specific benchmark but first rename the running task's ->comm[]
140 * to something meaningful:
141 */
142static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn,
143 int argc, const char **argv, const char *prefix)
163{ 144{
164 int i; 145 int size;
146 char *name;
147 int ret;
148
149 size = strlen(coll_name) + 1 + strlen(bench_name) + 1;
150
151 name = zalloc(size);
152 BUG_ON(!name);
153
154 scnprintf(name, size, "%s-%s", coll_name, bench_name);
155
156 prctl(PR_SET_NAME, name);
157 argv[0] = name;
158
159 ret = fn(argc, argv, prefix);
160
161 free(name);
162
163 return ret;
164}
165
166static void run_collection(struct collection *coll)
167{
168 struct bench *bench;
165 const char *argv[2]; 169 const char *argv[2];
166 struct bench_suite *suites = subsys->suites;
167 170
168 argv[1] = NULL; 171 argv[1] = NULL;
169 /* 172 /*
170 * TODO: 173 * TODO:
171 * preparing preset parameters for 174 *
175 * Preparing preset parameters for
172 * embedded, ordinary PC, HPC, etc... 176 * embedded, ordinary PC, HPC, etc...
173 * will be helpful 177 * would be helpful.
174 */ 178 */
175 for (i = 0; suites[i].fn; i++) { 179 for_each_bench(coll, bench) {
176 printf("# Running %s/%s benchmark...\n", 180 if (!bench->fn)
177 subsys->name, 181 break;
178 suites[i].name); 182 printf("# Running %s/%s benchmark...\n", coll->name, bench->name);
179 fflush(stdout); 183 fflush(stdout);
180 184
181 argv[1] = suites[i].name; 185 argv[1] = bench->name;
182 suites[i].fn(1, argv, NULL); 186 run_bench(coll->name, bench->name, bench->fn, 1, argv, NULL);
183 printf("\n"); 187 printf("\n");
184 } 188 }
185} 189}
186 190
187static void all_subsystem(void) 191static void run_all_collections(void)
188{ 192{
189 int i; 193 struct collection *coll;
190 for (i = 0; subsystems[i].suites; i++) 194
191 all_suite(&subsystems[i]); 195 for_each_collection(coll)
196 run_collection(coll);
192} 197}
193 198
194int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) 199int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
195{ 200{
196 int i, j, status = 0; 201 struct collection *coll;
202 int ret = 0;
197 203
198 if (argc < 2) { 204 if (argc < 2) {
199 /* No subsystem specified. */ 205 /* No collection specified. */
200 print_usage(); 206 print_usage();
201 goto end; 207 goto end;
202 } 208 }
@@ -206,7 +212,7 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
206 212
207 bench_format = bench_str2int(bench_format_str); 213 bench_format = bench_str2int(bench_format_str);
208 if (bench_format == BENCH_FORMAT_UNKNOWN) { 214 if (bench_format == BENCH_FORMAT_UNKNOWN) {
209 printf("Unknown format descriptor:%s\n", bench_format_str); 215 printf("Unknown format descriptor: '%s'\n", bench_format_str);
210 goto end; 216 goto end;
211 } 217 }
212 218
@@ -216,52 +222,51 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
216 } 222 }
217 223
218 if (!strcmp(argv[0], "all")) { 224 if (!strcmp(argv[0], "all")) {
219 all_subsystem(); 225 run_all_collections();
220 goto end; 226 goto end;
221 } 227 }
222 228
223 for (i = 0; subsystems[i].name; i++) { 229 for_each_collection(coll) {
224 if (strcmp(subsystems[i].name, argv[0])) 230 struct bench *bench;
231
232 if (strcmp(coll->name, argv[0]))
225 continue; 233 continue;
226 234
227 if (argc < 2) { 235 if (argc < 2) {
228 /* No suite specified. */ 236 /* No bench specified. */
229 dump_suites(i); 237 dump_benchmarks(coll);
230 goto end; 238 goto end;
231 } 239 }
232 240
233 if (!strcmp(argv[1], "all")) { 241 if (!strcmp(argv[1], "all")) {
234 all_suite(&subsystems[i]); 242 run_collection(coll);
235 goto end; 243 goto end;
236 } 244 }
237 245
238 for (j = 0; subsystems[i].suites[j].name; j++) { 246 for_each_bench(coll, bench) {
239 if (strcmp(subsystems[i].suites[j].name, argv[1])) 247 if (strcmp(bench->name, argv[1]))
240 continue; 248 continue;
241 249
242 if (bench_format == BENCH_FORMAT_DEFAULT) 250 if (bench_format == BENCH_FORMAT_DEFAULT)
243 printf("# Running %s/%s benchmark...\n", 251 printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name);
244 subsystems[i].name,
245 subsystems[i].suites[j].name);
246 fflush(stdout); 252 fflush(stdout);
247 status = subsystems[i].suites[j].fn(argc - 1, 253 ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1, prefix);
248 argv + 1, prefix);
249 goto end; 254 goto end;
250 } 255 }
251 256
252 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 257 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
253 dump_suites(i); 258 dump_benchmarks(coll);
254 goto end; 259 goto end;
255 } 260 }
256 261
257 printf("Unknown suite:%s for %s\n", argv[1], argv[0]); 262 printf("Unknown benchmark: '%s' for collection '%s'\n", argv[1], argv[0]);
258 status = 1; 263 ret = 1;
259 goto end; 264 goto end;
260 } 265 }
261 266
262 printf("Unknown subsystem:%s\n", argv[0]); 267 printf("Unknown collection: '%s'\n", argv[0]);
263 status = 1; 268 ret = 1;
264 269
265end: 270end:
266 return status; 271 return ret;
267} 272}