builtin-bench.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. * Available subsystem list:
  13. * sched ... scheduler and IPC mechanism
  14. * mem ... memory access performance
  15. *
  16. */
  17. #include "perf.h"
  18. #include "util/util.h"
  19. #include "util/parse-options.h"
  20. #include "builtin.h"
  21. #include "bench/bench.h"
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. struct bench_suite {
  26. const char *name;
  27. const char *summary;
  28. int (*fn)(int, const char **, const char *);
  29. };
  30. \
  31. /* sentinel: easy for help */
  32. #define suite_all { "all", "Test all benchmark suites", NULL }
  33. #ifdef LIBNUMA_SUPPORT
  34. static struct bench_suite numa_suites[] = {
  35. { "mem",
  36. "Benchmark for NUMA workloads",
  37. bench_numa },
  38. suite_all,
  39. { NULL,
  40. NULL,
  41. NULL }
  42. };
  43. #endif
  44. static struct bench_suite sched_suites[] = {
  45. { "messaging",
  46. "Benchmark for scheduler and IPC mechanisms",
  47. bench_sched_messaging },
  48. { "pipe",
  49. "Flood of communication over pipe() between two processes",
  50. bench_sched_pipe },
  51. suite_all,
  52. { NULL,
  53. NULL,
  54. NULL }
  55. };
  56. static struct bench_suite mem_suites[] = {
  57. { "memcpy",
  58. "Simple memory copy in various ways",
  59. bench_mem_memcpy },
  60. { "memset",
  61. "Simple memory set in various ways",
  62. bench_mem_memset },
  63. suite_all,
  64. { NULL,
  65. NULL,
  66. NULL }
  67. };
  68. struct bench_subsys {
  69. const char *name;
  70. const char *summary;
  71. struct bench_suite *suites;
  72. };
  73. static struct bench_subsys subsystems[] = {
  74. #ifdef LIBNUMA_SUPPORT
  75. { "numa",
  76. "NUMA scheduling and MM behavior",
  77. numa_suites },
  78. #endif
  79. { "sched",
  80. "scheduler and IPC mechanism",
  81. sched_suites },
  82. { "mem",
  83. "memory access performance",
  84. mem_suites },
  85. { "all", /* sentinel: easy for help */
  86. "all benchmark subsystem",
  87. NULL },
  88. { NULL,
  89. NULL,
  90. NULL }
  91. };
  92. static void dump_suites(int subsys_index)
  93. {
  94. int i;
  95. printf("# List of available suites for %s...\n\n",
  96. subsystems[subsys_index].name);
  97. for (i = 0; subsystems[subsys_index].suites[i].name; i++)
  98. printf("%14s: %s\n",
  99. subsystems[subsys_index].suites[i].name,
  100. subsystems[subsys_index].suites[i].summary);
  101. printf("\n");
  102. return;
  103. }
  104. static const char *bench_format_str;
  105. int bench_format = BENCH_FORMAT_DEFAULT;
  106. static const struct option bench_options[] = {
  107. OPT_STRING('f', "format", &bench_format_str, "default",
  108. "Specify format style"),
  109. OPT_END()
  110. };
  111. static const char * const bench_usage[] = {
  112. "perf bench [<common options>] <subsystem> <suite> [<options>]",
  113. NULL
  114. };
  115. static void print_usage(void)
  116. {
  117. int i;
  118. printf("Usage: \n");
  119. for (i = 0; bench_usage[i]; i++)
  120. printf("\t%s\n", bench_usage[i]);
  121. printf("\n");
  122. printf("# List of available subsystems...\n\n");
  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. static int bench_str2int(const char *str)
  129. {
  130. if (!str)
  131. return BENCH_FORMAT_DEFAULT;
  132. if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR))
  133. return BENCH_FORMAT_DEFAULT;
  134. else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR))
  135. return BENCH_FORMAT_SIMPLE;
  136. return BENCH_FORMAT_UNKNOWN;
  137. }
  138. static void all_suite(struct bench_subsys *subsys) /* FROM HERE */
  139. {
  140. int i;
  141. const char *argv[2];
  142. struct bench_suite *suites = subsys->suites;
  143. argv[1] = NULL;
  144. /*
  145. * TODO:
  146. * preparing preset parameters for
  147. * embedded, ordinary PC, HPC, etc...
  148. * will be helpful
  149. */
  150. for (i = 0; suites[i].fn; i++) {
  151. printf("# Running %s/%s benchmark...\n",
  152. subsys->name,
  153. suites[i].name);
  154. fflush(stdout);
  155. argv[1] = suites[i].name;
  156. suites[i].fn(1, argv, NULL);
  157. printf("\n");
  158. }
  159. }
  160. static void all_subsystem(void)
  161. {
  162. int i;
  163. for (i = 0; subsystems[i].suites; i++)
  164. all_suite(&subsystems[i]);
  165. }
  166. int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
  167. {
  168. int i, j, status = 0;
  169. if (argc < 2) {
  170. /* No subsystem specified. */
  171. print_usage();
  172. goto end;
  173. }
  174. argc = parse_options(argc, argv, bench_options, bench_usage,
  175. PARSE_OPT_STOP_AT_NON_OPTION);
  176. bench_format = bench_str2int(bench_format_str);
  177. if (bench_format == BENCH_FORMAT_UNKNOWN) {
  178. printf("Unknown format descriptor:%s\n", bench_format_str);
  179. goto end;
  180. }
  181. if (argc < 1) {
  182. print_usage();
  183. goto end;
  184. }
  185. if (!strcmp(argv[0], "all")) {
  186. all_subsystem();
  187. goto end;
  188. }
  189. for (i = 0; subsystems[i].name; i++) {
  190. if (strcmp(subsystems[i].name, argv[0]))
  191. continue;
  192. if (argc < 2) {
  193. /* No suite specified. */
  194. dump_suites(i);
  195. goto end;
  196. }
  197. if (!strcmp(argv[1], "all")) {
  198. all_suite(&subsystems[i]);
  199. goto end;
  200. }
  201. for (j = 0; subsystems[i].suites[j].name; j++) {
  202. if (strcmp(subsystems[i].suites[j].name, argv[1]))
  203. continue;
  204. if (bench_format == BENCH_FORMAT_DEFAULT)
  205. printf("# Running %s/%s benchmark...\n",
  206. subsystems[i].name,
  207. subsystems[i].suites[j].name);
  208. fflush(stdout);
  209. status = subsystems[i].suites[j].fn(argc - 1,
  210. argv + 1, prefix);
  211. goto end;
  212. }
  213. if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
  214. dump_suites(i);
  215. goto end;
  216. }
  217. printf("Unknown suite:%s for %s\n", argv[1], argv[0]);
  218. status = 1;
  219. goto end;
  220. }
  221. printf("Unknown subsystem:%s\n", argv[0]);
  222. status = 1;
  223. end:
  224. return status;
  225. }