186470930SIngo Molnar /* 286470930SIngo Molnar * builtin-stat.c 386470930SIngo Molnar * 486470930SIngo Molnar * Builtin stat command: Give a precise performance counters summary 586470930SIngo Molnar * overview about any workload, CPU or specific PID. 686470930SIngo Molnar * 786470930SIngo Molnar * Sample output: 886470930SIngo Molnar 986470930SIngo Molnar $ perf stat ~/hackbench 10 1086470930SIngo Molnar Time: 0.104 1186470930SIngo Molnar 1286470930SIngo Molnar Performance counter stats for '/home/mingo/hackbench': 1386470930SIngo Molnar 1486470930SIngo Molnar 1255.538611 task clock ticks # 10.143 CPU utilization factor 1586470930SIngo Molnar 54011 context switches # 0.043 M/sec 1686470930SIngo Molnar 385 CPU migrations # 0.000 M/sec 1786470930SIngo Molnar 17755 pagefaults # 0.014 M/sec 1886470930SIngo Molnar 3808323185 CPU cycles # 3033.219 M/sec 1986470930SIngo Molnar 1575111190 instructions # 1254.530 M/sec 2086470930SIngo Molnar 17367895 cache references # 13.833 M/sec 2186470930SIngo Molnar 7674421 cache misses # 6.112 M/sec 2286470930SIngo Molnar 2386470930SIngo Molnar Wall-clock time elapsed: 123.786620 msecs 2486470930SIngo Molnar 2586470930SIngo Molnar * 2686470930SIngo Molnar * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 2786470930SIngo Molnar * 2886470930SIngo Molnar * Improvements and fixes by: 2986470930SIngo Molnar * 3086470930SIngo Molnar * Arjan van de Ven <arjan@linux.intel.com> 3186470930SIngo Molnar * Yanmin Zhang <yanmin.zhang@intel.com> 3286470930SIngo Molnar * Wu Fengguang <fengguang.wu@intel.com> 3386470930SIngo Molnar * Mike Galbraith <efault@gmx.de> 3486470930SIngo Molnar * Paul Mackerras <paulus@samba.org> 356e750a8fSJaswinder Singh Rajput * Jaswinder Singh Rajput <jaswinder@kernel.org> 3686470930SIngo Molnar * 3786470930SIngo Molnar * Released under the GPL v2. (and only v2, not any later version) 3886470930SIngo Molnar */ 3986470930SIngo Molnar 4086470930SIngo Molnar #include "perf.h" 4186470930SIngo Molnar #include "builtin.h" 4286470930SIngo Molnar #include "util/util.h" 4386470930SIngo Molnar #include "util/parse-options.h" 4486470930SIngo Molnar #include "util/parse-events.h" 4586470930SIngo Molnar 4686470930SIngo Molnar #include <sys/prctl.h> 4742202dd5SIngo Molnar #include <math.h> 4886470930SIngo Molnar 49c3043569SJaswinder Singh Rajput static struct perf_counter_attr default_attrs[] = { 5086470930SIngo Molnar 51f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 52f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES}, 53f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 54f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 5586470930SIngo Molnar 56f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 57f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 58f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES}, 59f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES }, 60f4dbfa8fSPeter Zijlstra 6186470930SIngo Molnar }; 6286470930SIngo Molnar 6342202dd5SIngo Molnar #define MAX_RUN 100 6486470930SIngo Molnar 653d632595SJaswinder Singh Rajput static int system_wide = 0; 663d632595SJaswinder Singh Rajput static int verbose = 0; 67f37a291cSIngo Molnar static unsigned int nr_cpus = 0; 6842202dd5SIngo Molnar static int run_idx = 0; 6942202dd5SIngo Molnar 703d632595SJaswinder Singh Rajput static int run_count = 1; 713d632595SJaswinder Singh Rajput static int inherit = 1; 723d632595SJaswinder Singh Rajput static int scale = 1; 733d632595SJaswinder Singh Rajput static int target_pid = -1; 740cfb7a13SIngo Molnar static int null_run = 0; 7542202dd5SIngo Molnar 763d632595SJaswinder Singh Rajput static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 7742202dd5SIngo Molnar 789cffa8d5SPaul Mackerras static u64 runtime_nsecs[MAX_RUN]; 799cffa8d5SPaul Mackerras static u64 walltime_nsecs[MAX_RUN]; 809cffa8d5SPaul Mackerras static u64 runtime_cycles[MAX_RUN]; 8142202dd5SIngo Molnar 823d632595SJaswinder Singh Rajput static u64 event_res[MAX_RUN][MAX_COUNTERS][3]; 833d632595SJaswinder Singh Rajput static u64 event_scaled[MAX_RUN][MAX_COUNTERS]; 843d632595SJaswinder Singh Rajput 859cffa8d5SPaul Mackerras static u64 event_res_avg[MAX_COUNTERS][3]; 869cffa8d5SPaul Mackerras static u64 event_res_noise[MAX_COUNTERS][3]; 8742202dd5SIngo Molnar 889cffa8d5SPaul Mackerras static u64 event_scaled_avg[MAX_COUNTERS]; 8942202dd5SIngo Molnar 909cffa8d5SPaul Mackerras static u64 runtime_nsecs_avg; 919cffa8d5SPaul Mackerras static u64 runtime_nsecs_noise; 9242202dd5SIngo Molnar 939cffa8d5SPaul Mackerras static u64 walltime_nsecs_avg; 949cffa8d5SPaul Mackerras static u64 walltime_nsecs_noise; 9542202dd5SIngo Molnar 969cffa8d5SPaul Mackerras static u64 runtime_cycles_avg; 979cffa8d5SPaul Mackerras static u64 runtime_cycles_noise; 9886470930SIngo Molnar 99b9ebdcc0SJaswinder Singh Rajput #define MATCH_EVENT(t, c, counter) \ 100b9ebdcc0SJaswinder Singh Rajput (attrs[counter].type == PERF_TYPE_##t && \ 101b9ebdcc0SJaswinder Singh Rajput attrs[counter].config == PERF_COUNT_##c) 102b9ebdcc0SJaswinder Singh Rajput 103cca03c0aSJaswinder Singh Rajput #define ERR_PERF_OPEN \ 104cca03c0aSJaswinder Singh Rajput "Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" 105cca03c0aSJaswinder Singh Rajput 106051ae7f7SPaul Mackerras static void create_perf_stat_counter(int counter, int pid) 10786470930SIngo Molnar { 10886470930SIngo Molnar struct perf_counter_attr *attr = attrs + counter; 10986470930SIngo Molnar 11086470930SIngo Molnar if (scale) 11186470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 11286470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 11386470930SIngo Molnar 11486470930SIngo Molnar if (system_wide) { 115f37a291cSIngo Molnar unsigned int cpu; 116f37a291cSIngo Molnar 11786470930SIngo Molnar for (cpu = 0; cpu < nr_cpus; cpu++) { 11886470930SIngo Molnar fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); 119cca03c0aSJaswinder Singh Rajput if (fd[cpu][counter] < 0 && verbose) 120cca03c0aSJaswinder Singh Rajput fprintf(stderr, ERR_PERF_OPEN, counter, 121cca03c0aSJaswinder Singh Rajput fd[cpu][counter], strerror(errno)); 12286470930SIngo Molnar } 12386470930SIngo Molnar } else { 12486470930SIngo Molnar attr->inherit = inherit; 12586470930SIngo Molnar attr->disabled = 1; 12657e7986eSPaul Mackerras attr->enable_on_exec = 1; 12786470930SIngo Molnar 128051ae7f7SPaul Mackerras fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0); 129cca03c0aSJaswinder Singh Rajput if (fd[0][counter] < 0 && verbose) 130cca03c0aSJaswinder Singh Rajput fprintf(stderr, ERR_PERF_OPEN, counter, 131cca03c0aSJaswinder Singh Rajput fd[0][counter], strerror(errno)); 13286470930SIngo Molnar } 13386470930SIngo Molnar } 13486470930SIngo Molnar 13586470930SIngo Molnar /* 13686470930SIngo Molnar * Does the counter have nsecs as a unit? 13786470930SIngo Molnar */ 13886470930SIngo Molnar static inline int nsec_counter(int counter) 13986470930SIngo Molnar { 140b9ebdcc0SJaswinder Singh Rajput if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) || 141b9ebdcc0SJaswinder Singh Rajput MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) 14286470930SIngo Molnar return 1; 14386470930SIngo Molnar 14486470930SIngo Molnar return 0; 14586470930SIngo Molnar } 14686470930SIngo Molnar 14786470930SIngo Molnar /* 14886470930SIngo Molnar * Read out the results of a single counter: 14986470930SIngo Molnar */ 15086470930SIngo Molnar static void read_counter(int counter) 15186470930SIngo Molnar { 1529cffa8d5SPaul Mackerras u64 *count, single_count[3]; 153f37a291cSIngo Molnar unsigned int cpu; 154f37a291cSIngo Molnar size_t res, nv; 15586470930SIngo Molnar int scaled; 15686470930SIngo Molnar 15742202dd5SIngo Molnar count = event_res[run_idx][counter]; 15886470930SIngo Molnar 15986470930SIngo Molnar count[0] = count[1] = count[2] = 0; 16086470930SIngo Molnar 16186470930SIngo Molnar nv = scale ? 3 : 1; 16286470930SIngo Molnar for (cpu = 0; cpu < nr_cpus; cpu++) { 163743ee1f8SIngo Molnar if (fd[cpu][counter] < 0) 164743ee1f8SIngo Molnar continue; 165743ee1f8SIngo Molnar 1669cffa8d5SPaul Mackerras res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); 1679cffa8d5SPaul Mackerras assert(res == nv * sizeof(u64)); 168f37a291cSIngo Molnar 16942202dd5SIngo Molnar close(fd[cpu][counter]); 17042202dd5SIngo Molnar fd[cpu][counter] = -1; 17186470930SIngo Molnar 17286470930SIngo Molnar count[0] += single_count[0]; 17386470930SIngo Molnar if (scale) { 17486470930SIngo Molnar count[1] += single_count[1]; 17586470930SIngo Molnar count[2] += single_count[2]; 17686470930SIngo Molnar } 17786470930SIngo Molnar } 17886470930SIngo Molnar 17986470930SIngo Molnar scaled = 0; 18086470930SIngo Molnar if (scale) { 18186470930SIngo Molnar if (count[2] == 0) { 18242202dd5SIngo Molnar event_scaled[run_idx][counter] = -1; 18386470930SIngo Molnar count[0] = 0; 18486470930SIngo Molnar return; 18586470930SIngo Molnar } 18686470930SIngo Molnar 18786470930SIngo Molnar if (count[2] < count[1]) { 18842202dd5SIngo Molnar event_scaled[run_idx][counter] = 1; 18986470930SIngo Molnar count[0] = (unsigned long long) 19086470930SIngo Molnar ((double)count[0] * count[1] / count[2] + 0.5); 19186470930SIngo Molnar } 19286470930SIngo Molnar } 19386470930SIngo Molnar /* 19486470930SIngo Molnar * Save the full runtime - to allow normalization during printout: 19586470930SIngo Molnar */ 196b9ebdcc0SJaswinder Singh Rajput if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) 19742202dd5SIngo Molnar runtime_nsecs[run_idx] = count[0]; 198b9ebdcc0SJaswinder Singh Rajput if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter)) 19942202dd5SIngo Molnar runtime_cycles[run_idx] = count[0]; 20086470930SIngo Molnar } 20186470930SIngo Molnar 202f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv) 20386470930SIngo Molnar { 20486470930SIngo Molnar unsigned long long t0, t1; 20542202dd5SIngo Molnar int status = 0; 20686470930SIngo Molnar int counter; 20786470930SIngo Molnar int pid; 208051ae7f7SPaul Mackerras int child_ready_pipe[2], go_pipe[2]; 209051ae7f7SPaul Mackerras char buf; 21086470930SIngo Molnar 21186470930SIngo Molnar if (!system_wide) 21286470930SIngo Molnar nr_cpus = 1; 21386470930SIngo Molnar 214051ae7f7SPaul Mackerras if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) { 215051ae7f7SPaul Mackerras perror("failed to create pipes"); 216051ae7f7SPaul Mackerras exit(1); 217051ae7f7SPaul Mackerras } 218051ae7f7SPaul Mackerras 219051ae7f7SPaul Mackerras if ((pid = fork()) < 0) 220051ae7f7SPaul Mackerras perror("failed to fork"); 221051ae7f7SPaul Mackerras 222051ae7f7SPaul Mackerras if (!pid) { 223051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 224051ae7f7SPaul Mackerras close(go_pipe[1]); 225051ae7f7SPaul Mackerras fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 226051ae7f7SPaul Mackerras 227051ae7f7SPaul Mackerras /* 228051ae7f7SPaul Mackerras * Do a dummy execvp to get the PLT entry resolved, 229051ae7f7SPaul Mackerras * so we avoid the resolver overhead on the real 230051ae7f7SPaul Mackerras * execvp call. 231051ae7f7SPaul Mackerras */ 232051ae7f7SPaul Mackerras execvp("", (char **)argv); 233051ae7f7SPaul Mackerras 234051ae7f7SPaul Mackerras /* 235051ae7f7SPaul Mackerras * Tell the parent we're ready to go 236051ae7f7SPaul Mackerras */ 237051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 238051ae7f7SPaul Mackerras 239051ae7f7SPaul Mackerras /* 240051ae7f7SPaul Mackerras * Wait until the parent tells us to go. 241051ae7f7SPaul Mackerras */ 242051ae7f7SPaul Mackerras read(go_pipe[0], &buf, 1); 243051ae7f7SPaul Mackerras 244051ae7f7SPaul Mackerras execvp(argv[0], (char **)argv); 245051ae7f7SPaul Mackerras 246051ae7f7SPaul Mackerras perror(argv[0]); 247051ae7f7SPaul Mackerras exit(-1); 248051ae7f7SPaul Mackerras } 249051ae7f7SPaul Mackerras 250051ae7f7SPaul Mackerras /* 251051ae7f7SPaul Mackerras * Wait for the child to be ready to exec. 252051ae7f7SPaul Mackerras */ 253051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 254051ae7f7SPaul Mackerras close(go_pipe[0]); 255051ae7f7SPaul Mackerras read(child_ready_pipe[0], &buf, 1); 256051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 257051ae7f7SPaul Mackerras 25886470930SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 259051ae7f7SPaul Mackerras create_perf_stat_counter(counter, pid); 26086470930SIngo Molnar 26186470930SIngo Molnar /* 26286470930SIngo Molnar * Enable counters and exec the command: 26386470930SIngo Molnar */ 26486470930SIngo Molnar t0 = rdclock(); 26586470930SIngo Molnar 266051ae7f7SPaul Mackerras close(go_pipe[1]); 26742202dd5SIngo Molnar wait(&status); 26886470930SIngo Molnar 26986470930SIngo Molnar t1 = rdclock(); 27086470930SIngo Molnar 27142202dd5SIngo Molnar walltime_nsecs[run_idx] = t1 - t0; 27242202dd5SIngo Molnar 27342202dd5SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 27442202dd5SIngo Molnar read_counter(counter); 27542202dd5SIngo Molnar 27642202dd5SIngo Molnar return WEXITSTATUS(status); 27742202dd5SIngo Molnar } 27842202dd5SIngo Molnar 2799cffa8d5SPaul Mackerras static void print_noise(u64 *count, u64 *noise) 28042202dd5SIngo Molnar { 28142202dd5SIngo Molnar if (run_count > 1) 28242202dd5SIngo Molnar fprintf(stderr, " ( +- %7.3f%% )", 28342202dd5SIngo Molnar (double)noise[0]/(count[0]+1)*100.0); 28442202dd5SIngo Molnar } 28542202dd5SIngo Molnar 2869cffa8d5SPaul Mackerras static void nsec_printout(int counter, u64 *count, u64 *noise) 28742202dd5SIngo Molnar { 28842202dd5SIngo Molnar double msecs = (double)count[0] / 1000000; 28942202dd5SIngo Molnar 2906e750a8fSJaswinder Singh Rajput fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); 29142202dd5SIngo Molnar 292b9ebdcc0SJaswinder Singh Rajput if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { 29342202dd5SIngo Molnar if (walltime_nsecs_avg) 29442202dd5SIngo Molnar fprintf(stderr, " # %10.3f CPUs ", 29542202dd5SIngo Molnar (double)count[0] / (double)walltime_nsecs_avg); 29642202dd5SIngo Molnar } 29742202dd5SIngo Molnar print_noise(count, noise); 29842202dd5SIngo Molnar } 29942202dd5SIngo Molnar 3009cffa8d5SPaul Mackerras static void abs_printout(int counter, u64 *count, u64 *noise) 30142202dd5SIngo Molnar { 3026e750a8fSJaswinder Singh Rajput fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter)); 30342202dd5SIngo Molnar 30442202dd5SIngo Molnar if (runtime_cycles_avg && 305b9ebdcc0SJaswinder Singh Rajput MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { 30642202dd5SIngo Molnar fprintf(stderr, " # %10.3f IPC ", 30742202dd5SIngo Molnar (double)count[0] / (double)runtime_cycles_avg); 30842202dd5SIngo Molnar } else { 30942202dd5SIngo Molnar if (runtime_nsecs_avg) { 31042202dd5SIngo Molnar fprintf(stderr, " # %10.3f M/sec", 31142202dd5SIngo Molnar (double)count[0]/runtime_nsecs_avg*1000.0); 31242202dd5SIngo Molnar } 31342202dd5SIngo Molnar } 31442202dd5SIngo Molnar print_noise(count, noise); 31542202dd5SIngo Molnar } 31642202dd5SIngo Molnar 31742202dd5SIngo Molnar /* 31842202dd5SIngo Molnar * Print out the results of a single counter: 31942202dd5SIngo Molnar */ 32042202dd5SIngo Molnar static void print_counter(int counter) 32142202dd5SIngo Molnar { 3229cffa8d5SPaul Mackerras u64 *count, *noise; 32342202dd5SIngo Molnar int scaled; 32442202dd5SIngo Molnar 32542202dd5SIngo Molnar count = event_res_avg[counter]; 32642202dd5SIngo Molnar noise = event_res_noise[counter]; 32742202dd5SIngo Molnar scaled = event_scaled_avg[counter]; 32842202dd5SIngo Molnar 32942202dd5SIngo Molnar if (scaled == -1) { 3306e750a8fSJaswinder Singh Rajput fprintf(stderr, " %14s %-24s\n", 33142202dd5SIngo Molnar "<not counted>", event_name(counter)); 33242202dd5SIngo Molnar return; 33342202dd5SIngo Molnar } 33442202dd5SIngo Molnar 33542202dd5SIngo Molnar if (nsec_counter(counter)) 33642202dd5SIngo Molnar nsec_printout(counter, count, noise); 33742202dd5SIngo Molnar else 33842202dd5SIngo Molnar abs_printout(counter, count, noise); 33942202dd5SIngo Molnar 34042202dd5SIngo Molnar if (scaled) 341210ad39fSIngo Molnar fprintf(stderr, " (scaled from %.2f%%)", 342210ad39fSIngo Molnar (double) count[2] / count[1] * 100); 34342202dd5SIngo Molnar 34442202dd5SIngo Molnar fprintf(stderr, "\n"); 34542202dd5SIngo Molnar } 34642202dd5SIngo Molnar 34742202dd5SIngo Molnar /* 348ef281a19SIngo Molnar * normalize_noise noise values down to stddev: 34942202dd5SIngo Molnar */ 3509cffa8d5SPaul Mackerras static void normalize_noise(u64 *val) 35142202dd5SIngo Molnar { 35242202dd5SIngo Molnar double res; 35342202dd5SIngo Molnar 35442202dd5SIngo Molnar res = (double)*val / (run_count * sqrt((double)run_count)); 35542202dd5SIngo Molnar 3569cffa8d5SPaul Mackerras *val = (u64)res; 35742202dd5SIngo Molnar } 35842202dd5SIngo Molnar 3599cffa8d5SPaul Mackerras static void update_avg(const char *name, int idx, u64 *avg, u64 *val) 360ef281a19SIngo Molnar { 361ef281a19SIngo Molnar *avg += *val; 362ef281a19SIngo Molnar 363ef281a19SIngo Molnar if (verbose > 1) 364ef281a19SIngo Molnar fprintf(stderr, "debug: %20s[%d]: %Ld\n", name, idx, *val); 365ef281a19SIngo Molnar } 36642202dd5SIngo Molnar /* 36742202dd5SIngo Molnar * Calculate the averages and noises: 36842202dd5SIngo Molnar */ 36942202dd5SIngo Molnar static void calc_avg(void) 37042202dd5SIngo Molnar { 37142202dd5SIngo Molnar int i, j; 37242202dd5SIngo Molnar 373ef281a19SIngo Molnar if (verbose > 1) 374ef281a19SIngo Molnar fprintf(stderr, "\n"); 375ef281a19SIngo Molnar 37642202dd5SIngo Molnar for (i = 0; i < run_count; i++) { 377ef281a19SIngo Molnar update_avg("runtime", 0, &runtime_nsecs_avg, runtime_nsecs + i); 378ef281a19SIngo Molnar update_avg("walltime", 0, &walltime_nsecs_avg, walltime_nsecs + i); 379ef281a19SIngo Molnar update_avg("runtime_cycles", 0, &runtime_cycles_avg, runtime_cycles + i); 38042202dd5SIngo Molnar 38142202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 382ef281a19SIngo Molnar update_avg("counter/0", j, 383ef281a19SIngo Molnar event_res_avg[j]+0, event_res[i][j]+0); 384ef281a19SIngo Molnar update_avg("counter/1", j, 385ef281a19SIngo Molnar event_res_avg[j]+1, event_res[i][j]+1); 386ef281a19SIngo Molnar update_avg("counter/2", j, 387ef281a19SIngo Molnar event_res_avg[j]+2, event_res[i][j]+2); 388f37a291cSIngo Molnar if (event_scaled[i][j] != (u64)-1) 389ef281a19SIngo Molnar update_avg("scaled", j, 390ef281a19SIngo Molnar event_scaled_avg + j, event_scaled[i]+j); 391566747e6SIngo Molnar else 392566747e6SIngo Molnar event_scaled_avg[j] = -1; 39342202dd5SIngo Molnar } 39442202dd5SIngo Molnar } 39542202dd5SIngo Molnar runtime_nsecs_avg /= run_count; 39642202dd5SIngo Molnar walltime_nsecs_avg /= run_count; 39742202dd5SIngo Molnar runtime_cycles_avg /= run_count; 39842202dd5SIngo Molnar 39942202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 40042202dd5SIngo Molnar event_res_avg[j][0] /= run_count; 40142202dd5SIngo Molnar event_res_avg[j][1] /= run_count; 40242202dd5SIngo Molnar event_res_avg[j][2] /= run_count; 40342202dd5SIngo Molnar } 40442202dd5SIngo Molnar 40542202dd5SIngo Molnar for (i = 0; i < run_count; i++) { 40642202dd5SIngo Molnar runtime_nsecs_noise += 4079cffa8d5SPaul Mackerras abs((s64)(runtime_nsecs[i] - runtime_nsecs_avg)); 40842202dd5SIngo Molnar walltime_nsecs_noise += 4099cffa8d5SPaul Mackerras abs((s64)(walltime_nsecs[i] - walltime_nsecs_avg)); 41042202dd5SIngo Molnar runtime_cycles_noise += 4119cffa8d5SPaul Mackerras abs((s64)(runtime_cycles[i] - runtime_cycles_avg)); 41242202dd5SIngo Molnar 41342202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 41442202dd5SIngo Molnar event_res_noise[j][0] += 4159cffa8d5SPaul Mackerras abs((s64)(event_res[i][j][0] - event_res_avg[j][0])); 41642202dd5SIngo Molnar event_res_noise[j][1] += 4179cffa8d5SPaul Mackerras abs((s64)(event_res[i][j][1] - event_res_avg[j][1])); 41842202dd5SIngo Molnar event_res_noise[j][2] += 4199cffa8d5SPaul Mackerras abs((s64)(event_res[i][j][2] - event_res_avg[j][2])); 42042202dd5SIngo Molnar } 42142202dd5SIngo Molnar } 42242202dd5SIngo Molnar 423ef281a19SIngo Molnar normalize_noise(&runtime_nsecs_noise); 424ef281a19SIngo Molnar normalize_noise(&walltime_nsecs_noise); 425ef281a19SIngo Molnar normalize_noise(&runtime_cycles_noise); 42642202dd5SIngo Molnar 42742202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 428ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][0]); 429ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][1]); 430ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][2]); 43142202dd5SIngo Molnar } 43242202dd5SIngo Molnar } 43342202dd5SIngo Molnar 43442202dd5SIngo Molnar static void print_stat(int argc, const char **argv) 43542202dd5SIngo Molnar { 43642202dd5SIngo Molnar int i, counter; 43742202dd5SIngo Molnar 43842202dd5SIngo Molnar calc_avg(); 43942202dd5SIngo Molnar 44086470930SIngo Molnar fflush(stdout); 44186470930SIngo Molnar 44286470930SIngo Molnar fprintf(stderr, "\n"); 44386470930SIngo Molnar fprintf(stderr, " Performance counter stats for \'%s", argv[0]); 44486470930SIngo Molnar 44586470930SIngo Molnar for (i = 1; i < argc; i++) 44686470930SIngo Molnar fprintf(stderr, " %s", argv[i]); 44786470930SIngo Molnar 44842202dd5SIngo Molnar fprintf(stderr, "\'"); 44942202dd5SIngo Molnar if (run_count > 1) 45042202dd5SIngo Molnar fprintf(stderr, " (%d runs)", run_count); 45142202dd5SIngo Molnar fprintf(stderr, ":\n\n"); 45286470930SIngo Molnar 45386470930SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 45486470930SIngo Molnar print_counter(counter); 45586470930SIngo Molnar 45686470930SIngo Molnar fprintf(stderr, "\n"); 457566747e6SIngo Molnar fprintf(stderr, " %14.9f seconds time elapsed", 45842202dd5SIngo Molnar (double)walltime_nsecs_avg/1e9); 459566747e6SIngo Molnar if (run_count > 1) { 460566747e6SIngo Molnar fprintf(stderr, " ( +- %7.3f%% )", 461566747e6SIngo Molnar 100.0*(double)walltime_nsecs_noise/(double)walltime_nsecs_avg); 462566747e6SIngo Molnar } 463566747e6SIngo Molnar fprintf(stderr, "\n\n"); 46486470930SIngo Molnar } 46586470930SIngo Molnar 466f7b7c26eSPeter Zijlstra static volatile int signr = -1; 467f7b7c26eSPeter Zijlstra 46886470930SIngo Molnar static void skip_signal(int signo) 46986470930SIngo Molnar { 470f7b7c26eSPeter Zijlstra signr = signo; 471f7b7c26eSPeter Zijlstra } 472f7b7c26eSPeter Zijlstra 473f7b7c26eSPeter Zijlstra static void sig_atexit(void) 474f7b7c26eSPeter Zijlstra { 475f7b7c26eSPeter Zijlstra if (signr == -1) 476f7b7c26eSPeter Zijlstra return; 477f7b7c26eSPeter Zijlstra 478f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 479f7b7c26eSPeter Zijlstra kill(getpid(), signr); 48086470930SIngo Molnar } 48186470930SIngo Molnar 48286470930SIngo Molnar static const char * const stat_usage[] = { 48386470930SIngo Molnar "perf stat [<options>] <command>", 48486470930SIngo Molnar NULL 48586470930SIngo Molnar }; 48686470930SIngo Molnar 48786470930SIngo Molnar static const struct option options[] = { 48886470930SIngo Molnar OPT_CALLBACK('e', "event", NULL, "event", 48986470930SIngo Molnar "event selector. use 'perf list' to list available events", 49086470930SIngo Molnar parse_events), 49186470930SIngo Molnar OPT_BOOLEAN('i', "inherit", &inherit, 49286470930SIngo Molnar "child tasks inherit counters"), 49386470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 49486470930SIngo Molnar "stat events on existing pid"), 49586470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 49686470930SIngo Molnar "system-wide collection from all CPUs"), 49786470930SIngo Molnar OPT_BOOLEAN('S', "scale", &scale, 49886470930SIngo Molnar "scale/normalize counters"), 499743ee1f8SIngo Molnar OPT_BOOLEAN('v', "verbose", &verbose, 500743ee1f8SIngo Molnar "be more verbose (show counter open errors, etc)"), 50142202dd5SIngo Molnar OPT_INTEGER('r', "repeat", &run_count, 50242202dd5SIngo Molnar "repeat command and print average + stddev (max: 100)"), 5030cfb7a13SIngo Molnar OPT_BOOLEAN('n', "null", &null_run, 5040cfb7a13SIngo Molnar "null run - dont start any counters"), 50586470930SIngo Molnar OPT_END() 50686470930SIngo Molnar }; 50786470930SIngo Molnar 508f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used) 50986470930SIngo Molnar { 51042202dd5SIngo Molnar int status; 51142202dd5SIngo Molnar 51286470930SIngo Molnar argc = parse_options(argc, argv, options, stat_usage, 0); 51386470930SIngo Molnar if (!argc) 51486470930SIngo Molnar usage_with_options(stat_usage, options); 51542202dd5SIngo Molnar if (run_count <= 0 || run_count > MAX_RUN) 51642202dd5SIngo Molnar usage_with_options(stat_usage, options); 51786470930SIngo Molnar 518c3043569SJaswinder Singh Rajput /* Set attrs and nr_counters if no event is selected and !null_run */ 519c3043569SJaswinder Singh Rajput if (!null_run && !nr_counters) { 520c3043569SJaswinder Singh Rajput memcpy(attrs, default_attrs, sizeof(default_attrs)); 521c3043569SJaswinder Singh Rajput nr_counters = ARRAY_SIZE(default_attrs); 522c3043569SJaswinder Singh Rajput } 52386470930SIngo Molnar 52486470930SIngo Molnar nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 52586470930SIngo Molnar assert(nr_cpus <= MAX_NR_CPUS); 526f37a291cSIngo Molnar assert((int)nr_cpus >= 0); 52786470930SIngo Molnar 52886470930SIngo Molnar /* 52986470930SIngo Molnar * We dont want to block the signals - that would cause 53086470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 53186470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 53286470930SIngo Molnar * task, but being ignored by perf stat itself: 53386470930SIngo Molnar */ 534f7b7c26eSPeter Zijlstra atexit(sig_atexit); 53586470930SIngo Molnar signal(SIGINT, skip_signal); 53686470930SIngo Molnar signal(SIGALRM, skip_signal); 53786470930SIngo Molnar signal(SIGABRT, skip_signal); 53886470930SIngo Molnar 53942202dd5SIngo Molnar status = 0; 54042202dd5SIngo Molnar for (run_idx = 0; run_idx < run_count; run_idx++) { 54142202dd5SIngo Molnar if (run_count != 1 && verbose) 54242202dd5SIngo Molnar fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); 54342202dd5SIngo Molnar status = run_perf_stat(argc, argv); 54442202dd5SIngo Molnar } 54542202dd5SIngo Molnar 54642202dd5SIngo Molnar print_stat(argc, argv); 54742202dd5SIngo Molnar 54842202dd5SIngo Molnar return status; 54986470930SIngo Molnar } 550