diff options
| author | Stephane Eranian <eranian@google.com> | 2013-02-14 07:57:27 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-03-25 14:29:53 -0400 |
| commit | 86ee6e18f6cb43ab0cb67347bda5b6f5b016121d (patch) | |
| tree | 414e785b0ba86fc602ad286846cdfd9266568df6 | |
| parent | ebf3c675d7e4ba97568dd6daaa43b1af10046b29 (diff) | |
perf stat: Refactor aggregation code
Refactor aggregation code by introducing a single aggr_mode variable and an
enum for aggregation.
Also refactor cpumap code having to do with cpu to socket mappings. All in
preparation for extended modes, such as cpu -> core.
Also fix socket aggregation and ensure that sockets are printed in increasing
order.
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1360846649-6411-2-git-send-email-eranian@google.com
[ committer note: Fixup conflicts with a7e191c "--repeat forever" and
acf2892 "Use perf_evlist__prepare/start_workload()" ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/builtin-stat.c | 207 | ||||
| -rw-r--r-- | tools/perf/util/cpumap.c | 40 |
2 files changed, 147 insertions, 100 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ba0bdd87c279..ded34fc4df4f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
| @@ -68,7 +68,7 @@ | |||
| 68 | static void print_stat(int argc, const char **argv); | 68 | static void print_stat(int argc, const char **argv); |
| 69 | static void print_counter_aggr(struct perf_evsel *counter, char *prefix); | 69 | static void print_counter_aggr(struct perf_evsel *counter, char *prefix); |
| 70 | static void print_counter(struct perf_evsel *counter, char *prefix); | 70 | static void print_counter(struct perf_evsel *counter, char *prefix); |
| 71 | static void print_aggr_socket(char *prefix); | 71 | static void print_aggr(char *prefix); |
| 72 | 72 | ||
| 73 | static struct perf_evlist *evsel_list; | 73 | static struct perf_evlist *evsel_list; |
| 74 | 74 | ||
| @@ -76,11 +76,16 @@ static struct perf_target target = { | |||
| 76 | .uid = UINT_MAX, | 76 | .uid = UINT_MAX, |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | enum aggr_mode { | ||
| 80 | AGGR_NONE, | ||
| 81 | AGGR_GLOBAL, | ||
| 82 | AGGR_SOCKET, | ||
| 83 | }; | ||
| 84 | |||
| 79 | static int run_count = 1; | 85 | static int run_count = 1; |
| 80 | static bool no_inherit = false; | 86 | static bool no_inherit = false; |
| 81 | static bool scale = true; | 87 | static bool scale = true; |
| 82 | static bool no_aggr = false; | 88 | static enum aggr_mode aggr_mode = AGGR_GLOBAL; |
| 83 | static bool aggr_socket = false; | ||
| 84 | static pid_t child_pid = -1; | 89 | static pid_t child_pid = -1; |
| 85 | static bool null_run = false; | 90 | static bool null_run = false; |
| 86 | static int detailed_run = 0; | 91 | static int detailed_run = 0; |
| @@ -96,7 +101,8 @@ static bool sync_run = false; | |||
| 96 | static unsigned int interval = 0; | 101 | static unsigned int interval = 0; |
| 97 | static bool forever = false; | 102 | static bool forever = false; |
| 98 | static struct timespec ref_time; | 103 | static struct timespec ref_time; |
| 99 | static struct cpu_map *sock_map; | 104 | static struct cpu_map *aggr_map; |
| 105 | static int (*aggr_get_id)(struct cpu_map *m, int cpu); | ||
| 100 | 106 | ||
| 101 | static volatile int done = 0; | 107 | static volatile int done = 0; |
| 102 | 108 | ||
| @@ -355,41 +361,51 @@ static void print_interval(void) | |||
| 355 | struct timespec ts, rs; | 361 | struct timespec ts, rs; |
| 356 | char prefix[64]; | 362 | char prefix[64]; |
| 357 | 363 | ||
| 358 | if (no_aggr) { | 364 | if (aggr_mode == AGGR_GLOBAL) { |
| 359 | list_for_each_entry(counter, &evsel_list->entries, node) { | 365 | list_for_each_entry(counter, &evsel_list->entries, node) { |
| 360 | ps = counter->priv; | 366 | ps = counter->priv; |
| 361 | memset(ps->res_stats, 0, sizeof(ps->res_stats)); | 367 | memset(ps->res_stats, 0, sizeof(ps->res_stats)); |
| 362 | read_counter(counter); | 368 | read_counter_aggr(counter); |
| 363 | } | 369 | } |
| 364 | } else { | 370 | } else { |
| 365 | list_for_each_entry(counter, &evsel_list->entries, node) { | 371 | list_for_each_entry(counter, &evsel_list->entries, node) { |
| 366 | ps = counter->priv; | 372 | ps = counter->priv; |
| 367 | memset(ps->res_stats, 0, sizeof(ps->res_stats)); | 373 | memset(ps->res_stats, 0, sizeof(ps->res_stats)); |
| 368 | read_counter_aggr(counter); | 374 | read_counter(counter); |
| 369 | } | 375 | } |
| 370 | } | 376 | } |
| 377 | |||
| 371 | clock_gettime(CLOCK_MONOTONIC, &ts); | 378 | clock_gettime(CLOCK_MONOTONIC, &ts); |
| 372 | diff_timespec(&rs, &ts, &ref_time); | 379 | diff_timespec(&rs, &ts, &ref_time); |
| 373 | sprintf(prefix, "%6lu.%09lu%s", rs.tv_sec, rs.tv_nsec, csv_sep); | 380 | sprintf(prefix, "%6lu.%09lu%s", rs.tv_sec, rs.tv_nsec, csv_sep); |
| 374 | 381 | ||
| 375 | if (num_print_interval == 0 && !csv_output) { | 382 | if (num_print_interval == 0 && !csv_output) { |
| 376 | if (aggr_socket) | 383 | switch (aggr_mode) { |
| 384 | case AGGR_SOCKET: | ||
| 377 | fprintf(output, "# time socket cpus counts events\n"); | 385 | fprintf(output, "# time socket cpus counts events\n"); |
| 378 | else if (no_aggr) | 386 | break; |
| 387 | case AGGR_NONE: | ||
| 379 | fprintf(output, "# time CPU counts events\n"); | 388 | fprintf(output, "# time CPU counts events\n"); |
| 380 | else | 389 | break; |
| 390 | case AGGR_GLOBAL: | ||
| 391 | default: | ||
| 381 | fprintf(output, "# time counts events\n"); | 392 | fprintf(output, "# time counts events\n"); |
| 393 | } | ||
| 382 | } | 394 | } |
| 383 | 395 | ||
| 384 | if (++num_print_interval == 25) | 396 | if (++num_print_interval == 25) |
| 385 | num_print_interval = 0; | 397 | num_print_interval = 0; |
| 386 | 398 | ||
| 387 | if (aggr_socket) | 399 | switch (aggr_mode) { |
| 388 | print_aggr_socket(prefix); | 400 | case AGGR_SOCKET: |
| 389 | else if (no_aggr) { | 401 | print_aggr(prefix); |
| 402 | break; | ||
| 403 | case AGGR_NONE: | ||
| 390 | list_for_each_entry(counter, &evsel_list->entries, node) | 404 | list_for_each_entry(counter, &evsel_list->entries, node) |
| 391 | print_counter(counter, prefix); | 405 | print_counter(counter, prefix); |
| 392 | } else { | 406 | break; |
| 407 | case AGGR_GLOBAL: | ||
| 408 | default: | ||
| 393 | list_for_each_entry(counter, &evsel_list->entries, node) | 409 | list_for_each_entry(counter, &evsel_list->entries, node) |
| 394 | print_counter_aggr(counter, prefix); | 410 | print_counter_aggr(counter, prefix); |
| 395 | } | 411 | } |
| @@ -412,12 +428,6 @@ static int __run_perf_stat(int argc, const char **argv) | |||
| 412 | ts.tv_nsec = 0; | 428 | ts.tv_nsec = 0; |
| 413 | } | 429 | } |
| 414 | 430 | ||
| 415 | if (aggr_socket | ||
| 416 | && cpu_map__build_socket_map(evsel_list->cpus, &sock_map)) { | ||
| 417 | perror("cannot build socket map"); | ||
| 418 | return -1; | ||
| 419 | } | ||
| 420 | |||
| 421 | if (forks) { | 431 | if (forks) { |
| 422 | if (perf_evlist__prepare_workload(evsel_list, &target, argv, | 432 | if (perf_evlist__prepare_workload(evsel_list, &target, argv, |
| 423 | false, false) < 0) { | 433 | false, false) < 0) { |
| @@ -493,17 +503,17 @@ static int __run_perf_stat(int argc, const char **argv) | |||
| 493 | 503 | ||
| 494 | update_stats(&walltime_nsecs_stats, t1 - t0); | 504 | update_stats(&walltime_nsecs_stats, t1 - t0); |
| 495 | 505 | ||
| 496 | if (no_aggr) { | 506 | if (aggr_mode == AGGR_GLOBAL) { |
| 497 | list_for_each_entry(counter, &evsel_list->entries, node) { | ||
| 498 | read_counter(counter); | ||
| 499 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); | ||
| 500 | } | ||
| 501 | } else { | ||
| 502 | list_for_each_entry(counter, &evsel_list->entries, node) { | 507 | list_for_each_entry(counter, &evsel_list->entries, node) { |
| 503 | read_counter_aggr(counter); | 508 | read_counter_aggr(counter); |
| 504 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), | 509 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), |
| 505 | thread_map__nr(evsel_list->threads)); | 510 | thread_map__nr(evsel_list->threads)); |
| 506 | } | 511 | } |
| 512 | } else { | ||
| 513 | list_for_each_entry(counter, &evsel_list->entries, node) { | ||
| 514 | read_counter(counter); | ||
| 515 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); | ||
| 516 | } | ||
| 507 | } | 517 | } |
| 508 | 518 | ||
| 509 | return WEXITSTATUS(status); | 519 | return WEXITSTATUS(status); |
| @@ -556,26 +566,37 @@ static void print_noise(struct perf_evsel *evsel, double avg) | |||
| 556 | print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); | 566 | print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); |
| 557 | } | 567 | } |
| 558 | 568 | ||
| 559 | static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) | 569 | static void aggr_printout(struct perf_evsel *evsel, int cpu, int nr) |
| 560 | { | 570 | { |
| 561 | double msecs = avg / 1e6; | 571 | switch (aggr_mode) { |
| 562 | char cpustr[16] = { '\0', }; | 572 | case AGGR_SOCKET: |
| 563 | const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s"; | 573 | fprintf(output, "S%*d%s%*d%s", |
| 564 | |||
| 565 | if (aggr_socket) | ||
| 566 | sprintf(cpustr, "S%*d%s%*d%s", | ||
| 567 | csv_output ? 0 : -5, | 574 | csv_output ? 0 : -5, |
| 568 | cpu, | 575 | cpu, |
