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 suite (pseudo suite)", NULL }
  37
  38static 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
  51static 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
  61struct bench_subsys {
  62        const char *name;
  63        const char *summary;
  64        struct bench_suite *suites;
  65};
  66
  67static 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
  82static 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
  98static const char *bench_format_str;
  99int bench_format = BENCH_FORMAT_DEFAULT;
 100
 101static const struct option bench_options[] = {
 102        OPT_STRING('f', "format", &bench_format_str, "default",
 103                    "Specify format style"),
 104        OPT_END()
 105};
 106
 107static const char * const bench_usage[] = {
 108        "perf bench [<common options>] <subsystem> <suite> [<options>]",
 109        NULL
 110};
 111
 112static 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
 129static 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
 142static 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
 166static void all_subsystem(void)
 167{
 168        int i;
 169        for (i = 0; subsystems[i].suites; i++)
 170                all_suite(&subsystems[i]);
 171}
 172
 173int 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
 243end:
 244        return status;
 245}
 246