aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r--tools/perf/builtin-stat.c136
1 files changed, 54 insertions, 82 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 861f0aec77ae..e8cd4d81b06e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -51,13 +51,13 @@
51#include "util/evsel.h" 51#include "util/evsel.h"
52#include "util/debug.h" 52#include "util/debug.h"
53#include "util/color.h" 53#include "util/color.h"
54#include "util/stat.h"
54#include "util/header.h" 55#include "util/header.h"
55#include "util/cpumap.h" 56#include "util/cpumap.h"
56#include "util/thread.h" 57#include "util/thread.h"
57#include "util/thread_map.h" 58#include "util/thread_map.h"
58 59
59#include <sys/prctl.h> 60#include <sys/prctl.h>
60#include <math.h>
61#include <locale.h> 61#include <locale.h>
62 62
63#define DEFAULT_SEPARATOR " " 63#define DEFAULT_SEPARATOR " "
@@ -199,11 +199,6 @@ static int output_fd;
199 199
200static volatile int done = 0; 200static volatile int done = 0;
201 201
202struct stats
203{
204 double n, mean, M2;
205};
206
207struct perf_stat { 202struct perf_stat {
208 struct stats res_stats[3]; 203 struct stats res_stats[3];
209}; 204};
@@ -220,48 +215,14 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
220 evsel->priv = NULL; 215 evsel->priv = NULL;
221} 216}
222 217
223static void update_stats(struct stats *stats, u64 val) 218static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
224{
225 double delta;
226
227 stats->n++;
228 delta = val - stats->mean;
229 stats->mean += delta / stats->n;
230 stats->M2 += delta*(val - stats->mean);
231}
232
233static double avg_stats(struct stats *stats)
234{ 219{
235 return stats->mean; 220 return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
236} 221}
237 222
238/* 223static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
239 * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
240 *
241 * (\Sum n_i^2) - ((\Sum n_i)^2)/n
242 * s^2 = -------------------------------
243 * n - 1
244 *
245 * http://en.wikipedia.org/wiki/Stddev
246 *
247 * The std dev of the mean is related to the std dev by:
248 *
249 * s
250 * s_mean = -------
251 * sqrt(n)
252 *
253 */
254static double stddev_stats(struct stats *stats)
255{ 224{
256 double variance, variance_mean; 225 return perf_evsel__cpus(evsel)->nr;
257
258 if (!stats->n)
259 return 0.0;
260
261 variance = stats->M2 / (stats->n - 1);
262 variance_mean = variance / stats->n;
263
264 return sqrt(variance_mean);
265} 226}
266 227
267static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; 228static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
@@ -281,13 +242,9 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
281 struct perf_evsel *first) 242 struct perf_evsel *first)
282{ 243{
283 struct perf_event_attr *attr = &evsel->attr; 244 struct perf_event_attr *attr = &evsel->attr;
284 struct xyarray *group_fd = NULL;
285 bool exclude_guest_missing = false; 245 bool exclude_guest_missing = false;
286 int ret; 246 int ret;
287 247
288 if (group && evsel != first)
289 group_fd = first->fd;
290
291 if (scale) 248 if (scale)
292 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 249 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
293 PERF_FORMAT_TOTAL_TIME_RUNNING; 250 PERF_FORMAT_TOTAL_TIME_RUNNING;
@@ -299,8 +256,7 @@ retry:
299 evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; 256 evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
300 257
301 if (perf_target__has_cpu(&target)) { 258 if (perf_target__has_cpu(&target)) {
302 ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus, 259 ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
303 group, group_fd);
304 if (ret) 260 if (ret)
305 goto check_ret; 261 goto check_ret;
306 return 0; 262 return 0;
@@ -311,8 +267,7 @@ retry:
311 attr->enable_on_exec = 1; 267 attr->enable_on_exec = 1;
312 } 268 }
313 269
314 ret = perf_evsel__open_per_thread(evsel, evsel_list->threads, 270 ret = perf_evsel__open_per_thread(evsel, evsel_list->threads);
315 group, group_fd);
316 if (!ret) 271 if (!ret)
317 return 0; 272 return 0;
318 /* fall through */ 273 /* fall through */
@@ -382,7 +337,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
382 u64 *count = counter->counts->aggr.values; 337 u64 *count = counter->counts->aggr.values;
383 int i; 338 int i;
384 339
385 if (__perf_evsel__read(counter, evsel_list->cpus->nr, 340 if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
386 evsel_list->threads->nr, scale) < 0) 341 evsel_list->threads->nr, scale) < 0)
387 return -1; 342 return -1;
388 343
@@ -411,7 +366,7 @@ static int read_counter(struct perf_evsel *counter)
411 u64 *count; 366 u64 *count;
412 int cpu; 367 int cpu;
413 368
414 for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 369 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
415 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 370 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
416 return -1; 371 return -1;
417 372
@@ -423,7 +378,7 @@ static int read_counter(struct perf_evsel *counter)
423 return 0; 378 return 0;
424} 379}
425 380
426static int run_perf_stat(int argc __used, const char **argv) 381static int run_perf_stat(int argc __maybe_unused, const char **argv)
427{ 382{
428 unsigned long long t0, t1; 383 unsigned long long t0, t1;
429 struct perf_evsel *counter, *first; 384 struct perf_evsel *counter, *first;
@@ -434,7 +389,7 @@ static int run_perf_stat(int argc __used, const char **argv)
434 389
435 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 390 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
436 perror("failed to create pipes"); 391 perror("failed to create pipes");
437 exit(1); 392 return -1;
438 } 393 }
439 394
440 if (forks) { 395 if (forks) {
@@ -483,7 +438,10 @@ static int run_perf_stat(int argc __used, const char **argv)
483 close(child_ready_pipe[0]); 438 close(child_ready_pipe[0]);
484 } 439 }
485 440
486 first = list_entry(evsel_list->entries.next, struct perf_evsel, node); 441 if (group)
442 perf_evlist__set_leader(evsel_list);
443
444 first = perf_evlist__first(evsel_list);
487 445
488 list_for_each_entry(counter, &evsel_list->entries, node) { 446 list_for_each_entry(counter, &evsel_list->entries, node) {
489 if (create_perf_stat_counter(counter, first) < 0) { 447 if (create_perf_stat_counter(counter, first) < 0) {
@@ -513,13 +471,14 @@ static int run_perf_stat(int argc __used, const char **argv)
513 } 471 }
514 if (child_pid != -1) 472 if (child_pid != -1)
515 kill(child_pid, SIGTERM); 473 kill(child_pid, SIGTERM);
516 die("Not all events could be opened.\n"); 474
475 pr_err("Not all events could be opened.\n");
517 return -1; 476 return -1;
518 } 477 }
519 counter->supported = true; 478 counter->supported = true;
520 } 479 }
521 480
522 if (perf_evlist__set_filters(evsel_list)) { 481 if (perf_evlist__apply_filters(evsel_list)) {
523 error("failed to set filter with %d (%s)\n", errno, 482 error("failed to set filter with %d (%s)\n", errno,
524 strerror(errno)); 483 strerror(errno));
525 return -1; 484 return -1;
@@ -546,12 +505,12 @@ static int run_perf_stat(int argc __used, const char **argv)
546 if (no_aggr) { 505 if (no_aggr) {
547 list_for_each_entry(counter, &evsel_list->entries, node) { 506 list_for_each_entry(counter, &evsel_list->entries, node) {
548 read_counter(counter); 507 read_counter(counter);
549 perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); 508 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1);
550 } 509 }
551 } else { 510 } else {
552 list_for_each_entry(counter, &evsel_list->entries, node) { 511 list_for_each_entry(counter, &evsel_list->entries, node) {
553 read_counter_aggr(counter); 512 read_counter_aggr(counter);
554 perf_evsel__close_fd(counter, evsel_list->cpus->nr, 513 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
555 evsel_list->threads->nr); 514 evsel_list->threads->nr);
556 } 515 }
557 } 516 }
@@ -561,10 +520,7 @@ static int run_perf_stat(int argc __used, const char **argv)
561 520
562static void print_noise_pct(double total, double avg) 521static void print_noise_pct(double total, double avg)
563{ 522{
564 double pct = 0.0; 523 double pct = rel_stddev_stats(total, avg);
565
566 if (avg)
567 pct = 100.0*total/avg;
568 524
569 if (csv_output) 525 if (csv_output)
570 fprintf(output, "%s%.2f%%", csv_sep, pct); 526 fprintf(output, "%s%.2f%%", csv_sep, pct);
@@ -592,7 +548,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
592 if (no_aggr) 548 if (no_aggr)
593 sprintf(cpustr, "CPU%*d%s", 549 sprintf(cpustr, "CPU%*d%s",
594 csv_output ? 0 : -4, 550 csv_output ? 0 : -4,
595 evsel_list->cpus->map[cpu], csv_sep); 551 perf_evsel__cpus(evsel)->map[cpu], csv_sep);
596 552
597 fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel)); 553 fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
598 554
@@ -636,7 +592,9 @@ static const char *get_ratio_color(enum grc_type type, double ratio)
636 return color; 592 return color;
637} 593}
638 594
639static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) 595static void print_stalled_cycles_frontend(int cpu,
596 struct perf_evsel *evsel
597 __maybe_unused, double avg)
640{ 598{
641 double total, ratio = 0.0; 599 double total, ratio = 0.0;
642 const char *color; 600 const char *color;
@@ -653,7 +611,9 @@ static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __us
653 fprintf(output, " frontend cycles idle "); 611 fprintf(output, " frontend cycles idle ");
654} 612}
655 613
656static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) 614static void print_stalled_cycles_backend(int cpu,
615 struct perf_evsel *evsel
616 __maybe_unused, double avg)
657{ 617{
658 double total, ratio = 0.0; 618 double total, ratio = 0.0;
659 const char *color; 619 const char *color;
@@ -670,7 +630,9 @@ static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __use
670 fprintf(output, " backend cycles idle "); 630 fprintf(output, " backend cycles idle ");
671} 631}
672 632
673static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) 633static void print_branch_misses(int cpu,
634 struct perf_evsel *evsel __maybe_unused,
635 double avg)
674{ 636{
675 double total, ratio = 0.0; 637 double total, ratio = 0.0;
676 const char *color; 638 const char *color;
@@ -687,7 +649,9 @@ static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double
687 fprintf(output, " of all branches "); 649 fprintf(output, " of all branches ");
688} 650}
689 651
690static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 652static void print_l1_dcache_misses(int cpu,
653 struct perf_evsel *evsel __maybe_unused,
654 double avg)
691{ 655{
692 double total, ratio = 0.0; 656 double total, ratio = 0.0;
693 const char *color; 657 const char *color;
@@ -704,7 +668,9 @@ static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, dou
704 fprintf(output, " of all L1-dcache hits "); 668 fprintf(output, " of all L1-dcache hits ");
705} 669}
706 670
707static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 671static void print_l1_icache_misses(int cpu,
672 struct perf_evsel *evsel __maybe_unused,
673 double avg)
708{ 674{
709 double total, ratio = 0.0; 675 double total, ratio = 0.0;
710 const char *color; 676 const char *color;
@@ -721,7 +687,9 @@ static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, dou
721 fprintf(output, " of all L1-icache hits "); 687 fprintf(output, " of all L1-icache hits ");
722} 688}
723 689
724static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 690static void print_dtlb_cache_misses(int cpu,
691 struct perf_evsel *evsel __maybe_unused,
692 double avg)
725{ 693{
726 double total, ratio = 0.0; 694 double total, ratio = 0.0;
727 const char *color; 695 const char *color;
@@ -738,7 +706,9 @@ static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
738 fprintf(output, " of all dTLB cache hits "); 706 fprintf(output, " of all dTLB cache hits ");
739} 707}
740 708
741static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 709static void print_itlb_cache_misses(int cpu,
710 struct perf_evsel *evsel __maybe_unused,
711 double avg)
742{ 712{
743 double total, ratio = 0.0; 713 double total, ratio = 0.0;
744 const char *color; 714 const char *color;
@@ -755,7 +725,9 @@ static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
755 fprintf(output, " of all iTLB cache hits "); 725 fprintf(output, " of all iTLB cache hits ");
756} 726}
757 727
758static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 728static void print_ll_cache_misses(int cpu,
729 struct perf_evsel *evsel __maybe_unused,
730 double avg)
759{ 731{
760 double total, ratio = 0.0; 732 double total, ratio = 0.0;
761 const char *color; 733 const char *color;
@@ -788,7 +760,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
788 if (no_aggr) 760 if (no_aggr)
789 sprintf(cpustr, "CPU%*d%s", 761 sprintf(cpustr, "CPU%*d%s",
790 csv_output ? 0 : -4, 762 csv_output ? 0 : -4,
791 evsel_list->cpus->map[cpu], csv_sep); 763 perf_evsel__cpus(evsel)->map[cpu], csv_sep);
792 else 764 else
793 cpu = 0; 765 cpu = 0;
794 766
@@ -949,14 +921,14 @@ static void print_counter(struct perf_evsel *counter)
949 u64 ena, run, val; 921 u64 ena, run, val;
950 int cpu; 922 int cpu;
951 923
952 for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 924 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
953 val = counter->counts->cpu[cpu].val; 925 val = counter->counts->cpu[cpu].val;
954 ena = counter->counts->cpu[cpu].ena; 926 ena = counter->counts->cpu[cpu].ena;
955 run = counter->counts->cpu[cpu].run; 927 run = counter->counts->cpu[cpu].run;
956 if (run == 0 || ena == 0) { 928 if (run == 0 || ena == 0) {
957 fprintf(output, "CPU%*d%s%*s%s%*s", 929 fprintf(output, "CPU%*d%s%*s%s%*s",
958 csv_output ? 0 : -4, 930 csv_output ? 0 : -4,
959 evsel_list->cpus->map[cpu], csv_sep, 931 perf_evsel__cpus(counter)->map[cpu], csv_sep,
960 csv_output ? 0 : 18, 932 csv_output ? 0 : 18,
961 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 933 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
962 csv_sep, 934 csv_sep,
@@ -1061,8 +1033,8 @@ static const char * const stat_usage[] = {
1061 NULL 1033 NULL
1062}; 1034};
1063 1035
1064static int stat__set_big_num(const struct option *opt __used, 1036static int stat__set_big_num(const struct option *opt __maybe_unused,
1065 const char *s __used, int unset) 1037 const char *s __maybe_unused, int unset)
1066{ 1038{
1067 big_num_opt = unset ? 0 : 1; 1039 big_num_opt = unset ? 0 : 1;
1068 return 0; 1040 return 0;
@@ -1156,7 +1128,7 @@ static int add_default_attributes(void)
1156 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); 1128 return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs);
1157} 1129}
1158 1130
1159int cmd_stat(int argc, const char **argv, const char *prefix __used) 1131int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1160{ 1132{
1161 struct perf_evsel *pos; 1133 struct perf_evsel *pos;
1162 int status = -ENOMEM; 1134 int status = -ENOMEM;
@@ -1192,7 +1164,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1192 output = fopen(output_name, mode); 1164 output = fopen(output_name, mode);
1193 if (!output) { 1165 if (!output) {
1194 perror("failed to create output file"); 1166 perror("failed to create output file");
1195 exit(-1); 1167 return -1;
1196 } 1168 }
1197 clock_gettime(CLOCK_REALTIME, &tm); 1169 clock_gettime(CLOCK_REALTIME, &tm);
1198 fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); 1170 fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
@@ -1255,7 +1227,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1255 1227
1256 list_for_each_entry(pos, &evsel_list->entries, node) { 1228 list_for_each_entry(pos, &evsel_list->entries, node) {
1257 if (perf_evsel__alloc_stat_priv(pos) < 0 || 1229 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
1258 perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0) 1230 perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0)
1259 goto out_free_fd; 1231 goto out_free_fd;
1260 } 1232 }
1261 1233