~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/builtin-bench.c

Version: ~ [ linux-6.6-rc1 ] ~ [ linux-6.5.2 ] ~ [ linux-6.4.15 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.52 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.131 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.194 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.256 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.294 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.325 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp