linux/tools/perf/builtin-bench.c
<<
>>
Prefs
   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
  29struct 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#ifdef LIBNUMA_SUPPORT
  39static struct bench_suite numa_suites[] = {
  40        { "mem",
  41          "Benchmark for NUMA workloads",
  42          bench_numa },
  43        suite_all,
  44        { NULL,
  45          NULL,
  46          NULL                  }
  47};
  48#endif
  49
  50static struct bench_suite sched_suites[] = {
  51        { "messaging",
  52          "Benchmark for scheduler and IPC mechanisms",
  53          bench_sched_messaging },
  54        { "pipe",
  55          "Flood of communication over pipe() between two processes",
  56          bench_sched_pipe      },
  57        suite_all,
  58        { NULL,
  59          NULL,
  60          NULL                  }
  61};
  62
  63static struct bench_suite mem_suites[] = {
  64        { "memcpy",
  65          "Simple memory copy in various ways",
  66          bench_mem_memcpy },
  67        { "memset",
  68          "Simple memory set in various ways",
  69          bench_mem_memset },
  70        suite_all,
  71        { NULL,
  72          NULL,
  73          NULL             }
  74};
  75
  76struct bench_subsys {
  77        const char *name;
  78        const char *summary;
  79        struct bench_suite *suites;
  80};
  81
  82static struct bench_subsys subsystems[] = {
  83#ifdef LIBNUMA_SUPPORT
  84        { "numa",
  85          "NUMA scheduling and MM behavior",
  86          numa_suites },
  87#endif
  88        { "sched",
  89          "scheduler and IPC mechanism",
  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};
 101
 102static void dump_suites(int subsys_index)
 103{
 104        int i;
 105
 106        printf("# List of available suites for %s...\n\n",
 107               subsystems[subsys_index].name);
 108
 109        for (i = 0; subsystems[subsys_index].suites[i].name; i++)
 110                printf("%14s: %s\n",
 111                       subsystems[subsys_index].suites[i].name,
 112                       subsystems[subsys_index].suites[i].summary);
 113
 114        printf("\n");
 115        return;
 116}
 117
 118static const char *bench_format_str;
 119int bench_format = BENCH_FORMAT_DEFAULT;
 120
 121static const struct option bench_options[] = {
 122        OPT_STRING('f', "format", &bench_format_str, "default",
 123                    "Specify format style"),
 124        OPT_END()
 125};
 126
 127static const char * const bench_usage[] = {
 128        "perf bench [<common options>] <subsystem> <suite> [<options>]",
 129        NULL
 130};
 131
 132static void print_usage(void)
 133{
 134        int i;
 135
 136        printf("Usage: \n");
 137        for (i = 0; bench_usage[i]; i++)
 138                printf("\t%s\n", bench_usage[i]);
 139        printf("\n");
 140
 141        printf("# List of available subsystems...\n\n");
 142
 143        for (i = 0; subsystems[i].name; i++)
 144                printf("%14s: %s\n",
 145                       subsystems[i].name, subsystems[i].summary);
 146        printf("\n");
 147}
 148
 149static int bench_str2int(const char *str)
 150{
 151        if (!str)
 152                return BENCH_FORMAT_DEFAULT;
 153
 154        if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR))
 155                return BENCH_FORMAT_DEFAULT;
 156        else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR))
 157                return BENCH_FORMAT_SIMPLE;
 158
 159        return BENCH_FORMAT_UNKNOWN;
 160}
 161
 162static void all_suite(struct bench_subsys *subsys)        /* FROM HERE */
 163{
 164        int i;
 165        const char *argv[2];
 166        struct bench_suite *suites = subsys->suites;
 167
 168        argv[1] = NULL;
 169        /*
 170         * TODO:
 171         * preparing preset parameters for
 172         * embedded, ordinary PC, HPC, etc...
 173         * will be helpful
 174         */
 175        for (i = 0; suites[i].fn; i++) {
 176                printf("# Running %s/%s benchmark...\n",
 177                       subsys->name,
 178                       suites[i].name);
 179                fflush(stdout);
 180
 181                argv[1] = suites[i].name;
 182                suites[i].fn(1, argv, NULL);
 183                printf("\n");
 184        }
 185}
 186
 187static void all_subsystem(void)
 188{
 189        int i;
 190        for (i = 0; subsystems[i].suites; i++)
 191                all_suite(&subsystems[i]);
 192}
 193
 194int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
 195{
 196        int i, j, status = 0;
 197
 198        if (argc < 2) {
 199                /* No subsystem specified. */
 200                print_usage();
 201                goto end;
 202        }
 203
 204        argc = parse_options(argc, argv, bench_options, bench_usage,
 205                             PARSE_OPT_STOP_AT_NON_OPTION);
 206
 207        bench_format = bench_str2int(bench_format_str);
 208        if (bench_format == BENCH_FORMAT_UNKNOWN) {
 209                printf("Unknown format descriptor:%s\n", bench_format_str);
 210                goto end;
 211        }
 212
 213        if (argc < 1) {
 214                print_usage();
 215                goto end;
 216        }
 217
 218        if (!strcmp(argv[0], "all")) {
 219                all_subsystem();
 220                goto end;
 221        }
 222
 223        for (i = 0; subsystems[i].name; i++) {
 224                if (strcmp(subsystems[i].name, argv[0]))
 225                        continue;
 226
 227                if (argc < 2) {
 228                        /* No suite specified. */
 229                        dump_suites(i);
 230                        goto end;
 231                }
 232
 233                if (!strcmp(argv[1], "all")) {
 234                        all_suite(&subsystems[i]);
 235                        goto end;
 236                }
 237
 238                for (j = 0; subsystems[i].suites[j].name; j++) {
 239                        if (strcmp(subsystems[i].suites[j].name, argv[1]))
 240                                continue;
 241
 242                        if (bench_format == BENCH_FORMAT_DEFAULT)
 243                                printf("# Running %s/%s benchmark...\n",
 244                                       subsystems[i].name,
 245                                       subsystems[i].suites[j].name);
 246                        fflush(stdout);
 247                        status = subsystems[i].suites[j].fn(argc - 1,
 248                                                            argv + 1, prefix);
 249                        goto end;
 250                }
 251
 252                if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
 253                        dump_suites(i);
 254                        goto end;
 255                }
 256
 257                printf("Unknown suite:%s for %s\n", argv[1], argv[0]);
 258                status = 1;
 259                goto end;
 260        }
 261
 262        printf("Unknown subsystem:%s\n", argv[0]);
 263        status = 1;
 264
 265end:
 266        return status;
 267}
 268