diff options
| author | Stephane Eranian <eranian@google.com> | 2010-12-01 11:49:05 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-12-01 16:47:41 -0500 |
| commit | d7470b6afca85ed4388fff57fc9d89f5a3be02ff (patch) | |
| tree | f170c6e53e53448649c6658ec0208f051b248a1c | |
| parent | 201e0b06efee80ce090579aa165c65c3d0836d95 (diff) | |
perf stat: Add csv-style output
This patch adds an option (-x/--field-separator) to print counts using a
CSV-style output. The user can pass a custom separator. This makes it very easy
to import counts directly into your favorite spreadsheet without having to
write scripts.
Example:
$ perf stat --field-separator=, -a -- sleep 1
4009.961740,task-clock-msecs
13,context-switches
2,CPU-migrations
189,page-faults
9596385684,cycles
3493659441,instructions
872897069,branches
41562,branch-misses
22424,cache-references
1289,cache-misses
Works also in non-aggregated mode:
$ perf stat -x , -a -A -- sleep 1
CPU0,1002.526168,task-clock-msecs
CPU1,1002.528365,task-clock-msecs
CPU2,1002.523360,task-clock-msecs
CPU3,1002.519878,task-clock-msecs
CPU0,1,context-switches
CPU1,5,context-switches
CPU2,5,context-switches
CPU3,6,context-switches
CPU0,0,CPU-migrations
CPU1,1,CPU-migrations
CPU2,0,CPU-migrations
CPU3,1,CPU-migrations
CPU0,2,page-faults
CPU1,6,page-faults
CPU2,9,page-faults
CPU3,174,page-faults
CPU0,2399439771,cycles
CPU1,2380369063,cycles
CPU2,2399142710,cycles
CPU3,2373161192,cycles
CPU0,872900618,instructions
CPU1,873030960,instructions
CPU2,872714525,instructions
CPU3,874460580,instructions
CPU0,221556839,branches
CPU1,218134342,branches
CPU2,218161730,branches
CPU3,218284093,branches
CPU0,18556,branch-misses
CPU1,1449,branch-misses
CPU2,3447,branch-misses
CPU3,12714,branch-misses
CPU0,8330,cache-references
CPU1,313844,cache-references
CPU2,47993728,cache-references
CPU3,826481,cache-references
CPU0,272,cache-misses
CPU1,5360,cache-misses
CPU2,1342193,cache-misses
CPU3,13992,cache-misses
This second version adds the ability to name a separator and uses
field-separator as the long option to be consistent with perf report.
Commiter note: Since we enabled --big-num by default in 201e0b0 and -x can't be
used with it, we need to notice if the user explicitely enabled or disabled -B,
add code to disable big_num if the user didn't explicitely set --big_num when
-x is used.
Cc: David S. Miller <davem@davemloft.net>
Cc: Frederik Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: paulus@samba.org
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Robert Richter <robert.richter@amd.com>
LKML-Reference: <4cf68aa7.0fedd80a.5294.1203@mx.google.com>
Signed-off-by: Stephane Eranian <eranian@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/Documentation/perf-stat.txt | 5 | ||||
| -rw-r--r-- | tools/perf/builtin-stat.c | 144 |
2 files changed, 109 insertions, 40 deletions
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index c469ba56c076..b6da7affbbee 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt | |||
| @@ -78,6 +78,11 @@ This option is only valid in system-wide mode. | |||
| 78 | --verbose:: | 78 | --verbose:: |
| 79 | be more verbose (show counter open errors, etc) | 79 | be more verbose (show counter open errors, etc) |
| 80 | 80 | ||
| 81 | -x SEP:: | ||
| 82 | --field-separator SEP:: | ||
| 83 | print counts using a CSV-style output to make it easy to import directly into | ||
| 84 | spreadsheets. Columns are separated by the string specified in SEP. | ||
| 85 | |||
| 81 | EXAMPLES | 86 | EXAMPLES |
| 82 | -------- | 87 | -------- |
| 83 | 88 | ||
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index acbf7ccd9d07..7ff746da7e6c 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
| @@ -52,6 +52,8 @@ | |||
| 52 | #include <math.h> | 52 | #include <math.h> |
| 53 | #include <locale.h> | 53 | #include <locale.h> |
| 54 | 54 | ||
| 55 | #define DEFAULT_SEPARATOR " " | ||
| 56 | |||
| 55 | static struct perf_event_attr default_attrs[] = { | 57 | static struct perf_event_attr default_attrs[] = { |
| 56 | 58 | ||
| 57 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, | 59 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, |
| @@ -83,7 +85,10 @@ static int thread_num = 0; | |||
| 83 | static pid_t child_pid = -1; | 85 | static pid_t child_pid = -1; |
| 84 | static bool null_run = false; | 86 | static bool null_run = false; |
| 85 | static bool big_num = true; | 87 | static bool big_num = true; |
| 88 | static int big_num_opt = -1; | ||
| 86 | static const char *cpu_list; | 89 | static const char *cpu_list; |
| 90 | static const char *csv_sep = NULL; | ||
| 91 | static bool csv_output = false; | ||
| 87 | 92 | ||
| 88 | 93 | ||
| 89 | static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; | 94 | static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; |
| @@ -449,12 +454,18 @@ static void print_noise(int counter, double avg) | |||
| 449 | static void nsec_printout(int cpu, int counter, double avg) | 454 | static void nsec_printout(int cpu, int counter, double avg) |
| 450 | { | 455 | { |
| 451 | double msecs = avg / 1e6; | 456 | double msecs = avg / 1e6; |
| 457 | char cpustr[16] = { '\0', }; | ||
| 458 | const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s"; | ||
| 452 | 459 | ||
| 453 | if (no_aggr) | 460 | if (no_aggr) |
| 454 | fprintf(stderr, "CPU%-4d %18.6f %-24s", | 461 | sprintf(cpustr, "CPU%*d%s", |
| 455 | cpumap[cpu], msecs, event_name(counter)); | 462 | csv_output ? 0 : -4, |
| 456 | else | 463 | cpumap[cpu], csv_sep); |
| 457 | fprintf(stderr, " %18.6f %-24s", msecs, event_name(counter)); | 464 | |
| 465 | fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(counter)); | ||
| 466 | |||
| 467 | if (csv_output) | ||
| 468 | return; | ||
| 458 | 469 | ||
| 459 | if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { | 470 | if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { |
| 460 | fprintf(stderr, " # %10.3f CPUs ", | 471 | fprintf(stderr, " # %10.3f CPUs ", |
| @@ -466,18 +477,26 @@ static void abs_printout(int cpu, int counter, double avg) | |||
| 466 | { | 477 | { |
| 467 | double total, ratio = 0.0; | 478 | double total, ratio = 0.0; |
| 468 | char cpustr[16] = { '\0', }; | 479 | char cpustr[16] = { '\0', }; |
| 480 | const char *fmt; | ||
| 481 | |||
| 482 | if (csv_output) | ||
| 483 | fmt = "%s%.0f%s%s"; | ||
| 484 | else if (big_num) | ||
| 485 | fmt = "%s%'18.0f%s%-24s"; | ||
| 486 | else | ||
| 487 | fmt = "%s%18.0f%s%-24s"; | ||
| 469 | 488 | ||
| 470 | if (no_aggr) | 489 | if (no_aggr) |
| 471 | sprintf(cpustr, "CPU%-4d", cpumap[cpu]); | 490 | sprintf(cpustr, "CPU%*d%s", |
| 491 | csv_output ? 0 : -4, | ||
| 492 | cpumap[cpu], csv_sep); | ||
| 472 | else | 493 | else |
| 473 | cpu = 0; | 494 | cpu = 0; |
| 474 | 495 | ||
| 475 | if (big_num) | 496 | fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(counter)); |
| 476 | fprintf(stderr, "%s %'18.0f %-24s", | 497 | |
| 477 | cpustr, avg, event_name(counter)); | 498 | if (csv_output) |
| 478 | else | 499 | return; |
| 479 | fprintf(stderr, "%s %18.0f %-24s", | ||
| 480 | cpustr, avg, event_name(counter)); | ||
| 481 | 500 | ||
| 482 | if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { | 501 | if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { |
| 483 | total = avg_stats(&runtime_cycles_stats[cpu]); | 502 | total = avg_stats(&runtime_cycles_stats[cpu]); |
| @@ -515,8 +534,9 @@ static void print_counter_aggr(int counter) | |||
| 515 | int scaled = event_scaled[counter]; | 534 | int scaled = event_scaled[counter]; |
| 516 | 535 | ||
| 517 | if (scaled == -1) { | 536 | if (scaled == -1) { |
| 518 | fprintf(stderr, " %18s %-24s\n", | 537 | fprintf(stderr, "%*s%s%-24s\n", |
| 519 | "<not counted>", event_name(counter)); | 538 | csv_output ? 0 : 18, |
| 539 | "<not counted>", csv_sep, event_name(counter)); | ||
| 520 | return; | 540 | return; |
| 521 | } | 541 | } |
| 522 | 542 | ||
| @@ -525,6 +545,11 @@ static void print_counter_aggr(int counter) | |||
| 525 | else | 545 | else |
| 526 | abs_printout(-1, counter, avg); | 546 | abs_printout(-1, counter, avg); |
| 527 | 547 | ||
| 548 | if (csv_output) { | ||
| 549 | fputc('\n', stderr); | ||
| 550 | return; | ||
| 551 | } | ||
| 552 | |||
| 528 | print_noise(counter, avg); | 553 | print_noise(counter, avg); |
| 529 | 554 | ||
| 530 | if (scaled) { | 555 | if (scaled) { |
| @@ -554,8 +579,12 @@ static void print_counter(int counter) | |||
| 554 | ena = cpu_counts[cpu][counter].ena; | 579 | ena = cpu_counts[cpu][counter].ena; |
| 555 | run = cpu_counts[cpu][counter].run; | 580 | run = cpu_counts[cpu][counter].run; |
| 556 | if (run == 0 || ena == 0) { | 581 | if (run == 0 || ena == 0) { |
| 557 | fprintf(stderr, "CPU%-4d %18s %-24s", cpumap[cpu], | 582 | fprintf(stderr, "CPU%*d%s%*s%s%-24s", |
| 558 | "<not counted>", event_name(counter)); | 583 | csv_output ? 0 : -4, |
| 584 | cpumap[cpu], csv_sep, | ||
| 585 | csv_output ? 0 : 18, | ||
| 586 | "<not counted>", csv_sep, | ||
| 587 | event_name(counter)); | ||
| 559 | 588 | ||
| 560 | fprintf(stderr, "\n"); | 589 | fprintf(stderr, "\n"); |
| 561 | continue; | 590 | continue; |
| @@ -566,11 +595,13 @@ static void print_counter(int counter) | |||
| 566 | else | 595 | else |
| 567 | abs_printout(cpu, counter, val); | 596 | abs_printout(cpu, counter, val); |
| 568 | 597 | ||
| 569 | print_noise(counter, 1.0); | 598 | if (!csv_output) { |
| 599 | print_noise(counter, 1.0); | ||
| 570 | 600 | ||
| 571 | if (run != ena) { | 601 | if (run != ena) { |
| 572 | fprintf(stderr, " (scaled from %.2f%%)", | 602 | fprintf(stderr, " (scaled from %.2f%%)", |
| 573 | 100.0 * run / ena); | 603 | 100.0 * run / ena); |
| 604 | } | ||
| 574 | } | 605 | } |
| 575 | fprintf(stderr, "\n"); | 606 | fprintf(stderr, "\n"); |
| 576 | } | 607 | } |
| @@ -582,21 +613,23 @@ static void print_stat(int argc, const char **argv) | |||
| 582 | 613 | ||
| 583 | fflush(stdout); | 614 | fflush(stdout); |
| 584 | 615 | ||
| 585 | fprintf(stderr, "\n"); | 616 | if (!csv_output) { |
| 586 | fprintf(stderr, " Performance counter stats for "); | 617 | fprintf(stderr, "\n"); |
| 587 | if(target_pid == -1 && target_tid == -1) { | 618 | fprintf(stderr, " Performance counter stats for "); |
| 588 | fprintf(stderr, "\'%s", argv[0]); | 619 | if(target_pid == -1 && target_tid == -1) { |
| 589 | for (i = 1; i < argc; i++) | 620 | fprintf(stderr, "\'%s", argv[0]); |
| 590 | fprintf(stderr, " %s", argv[i]); | 621 | for (i = 1; i < argc; i++) |
