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> 3586470930SIngo Molnar * 3686470930SIngo Molnar * Released under the GPL v2. (and only v2, not any later version) 3786470930SIngo Molnar */ 3886470930SIngo Molnar 3986470930SIngo Molnar #include "perf.h" 4086470930SIngo Molnar #include "builtin.h" 4186470930SIngo Molnar #include "util/util.h" 4286470930SIngo Molnar #include "util/parse-options.h" 4386470930SIngo Molnar #include "util/parse-events.h" 4486470930SIngo Molnar 4586470930SIngo Molnar #include <sys/prctl.h> 4642202dd5SIngo Molnar #include <math.h> 4786470930SIngo Molnar 4886470930SIngo Molnar static struct perf_counter_attr default_attrs[MAX_COUNTERS] = { 4986470930SIngo Molnar 50f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 51f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES}, 52f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 53f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 5486470930SIngo Molnar 55f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 56f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 57f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES}, 58f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES }, 59f4dbfa8fSPeter Zijlstra 6086470930SIngo Molnar }; 6186470930SIngo Molnar 6286470930SIngo Molnar static int system_wide = 0; 6386470930SIngo Molnar static int inherit = 1; 64743ee1f8SIngo Molnar static int verbose = 0; 6586470930SIngo Molnar 6686470930SIngo Molnar static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 6786470930SIngo Molnar 6886470930SIngo Molnar static int target_pid = -1; 6986470930SIngo Molnar static int nr_cpus = 0; 7086470930SIngo Molnar static unsigned int page_size; 7186470930SIngo Molnar 7286470930SIngo Molnar static int scale = 1; 7386470930SIngo Molnar 7486470930SIngo Molnar static const unsigned int default_count[] = { 7586470930SIngo Molnar 1000000, 7686470930SIngo Molnar 1000000, 7786470930SIngo Molnar 10000, 7886470930SIngo Molnar 10000, 7986470930SIngo Molnar 1000000, 8086470930SIngo Molnar 10000, 8186470930SIngo Molnar }; 8286470930SIngo Molnar 8342202dd5SIngo Molnar #define MAX_RUN 100 8486470930SIngo Molnar 8542202dd5SIngo Molnar static int run_count = 1; 8642202dd5SIngo Molnar static int run_idx = 0; 8742202dd5SIngo Molnar 8842202dd5SIngo Molnar static __u64 event_res[MAX_RUN][MAX_COUNTERS][3]; 8942202dd5SIngo Molnar static __u64 event_scaled[MAX_RUN][MAX_COUNTERS]; 9042202dd5SIngo Molnar 9142202dd5SIngo Molnar //static __u64 event_hist[MAX_RUN][MAX_COUNTERS][3]; 9242202dd5SIngo Molnar 9342202dd5SIngo Molnar 9442202dd5SIngo Molnar static __u64 runtime_nsecs[MAX_RUN]; 9542202dd5SIngo Molnar static __u64 walltime_nsecs[MAX_RUN]; 9642202dd5SIngo Molnar static __u64 runtime_cycles[MAX_RUN]; 9742202dd5SIngo Molnar 9842202dd5SIngo Molnar static __u64 event_res_avg[MAX_COUNTERS][3]; 9942202dd5SIngo Molnar static __u64 event_res_noise[MAX_COUNTERS][3]; 10042202dd5SIngo Molnar 10142202dd5SIngo Molnar static __u64 event_scaled_avg[MAX_COUNTERS]; 10242202dd5SIngo Molnar 10342202dd5SIngo Molnar static __u64 runtime_nsecs_avg; 10442202dd5SIngo Molnar static __u64 runtime_nsecs_noise; 10542202dd5SIngo Molnar 10642202dd5SIngo Molnar static __u64 walltime_nsecs_avg; 10742202dd5SIngo Molnar static __u64 walltime_nsecs_noise; 10842202dd5SIngo Molnar 10942202dd5SIngo Molnar static __u64 runtime_cycles_avg; 11042202dd5SIngo Molnar static __u64 runtime_cycles_noise; 11186470930SIngo Molnar 112743ee1f8SIngo Molnar static void create_perf_stat_counter(int counter) 11386470930SIngo Molnar { 11486470930SIngo Molnar struct perf_counter_attr *attr = attrs + counter; 11586470930SIngo Molnar 11686470930SIngo Molnar if (scale) 11786470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 11886470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 11986470930SIngo Molnar 12086470930SIngo Molnar if (system_wide) { 12186470930SIngo Molnar int cpu; 12286470930SIngo Molnar for (cpu = 0; cpu < nr_cpus; cpu ++) { 12386470930SIngo Molnar fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); 124743ee1f8SIngo Molnar if (fd[cpu][counter] < 0 && verbose) { 125743ee1f8SIngo Molnar printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[cpu][counter], strerror(errno)); 12686470930SIngo Molnar } 12786470930SIngo Molnar } 12886470930SIngo Molnar } else { 12986470930SIngo Molnar attr->inherit = inherit; 13086470930SIngo Molnar attr->disabled = 1; 13186470930SIngo Molnar 13286470930SIngo Molnar fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0); 133743ee1f8SIngo Molnar if (fd[0][counter] < 0 && verbose) { 134743ee1f8SIngo Molnar printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[0][counter], strerror(errno)); 13586470930SIngo Molnar } 13686470930SIngo Molnar } 13786470930SIngo Molnar } 13886470930SIngo Molnar 13986470930SIngo Molnar /* 14086470930SIngo Molnar * Does the counter have nsecs as a unit? 14186470930SIngo Molnar */ 14286470930SIngo Molnar static inline int nsec_counter(int counter) 14386470930SIngo Molnar { 14486470930SIngo Molnar if (attrs[counter].type != PERF_TYPE_SOFTWARE) 14586470930SIngo Molnar return 0; 14686470930SIngo Molnar 147f4dbfa8fSPeter Zijlstra if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK) 14886470930SIngo Molnar return 1; 14986470930SIngo Molnar 150f4dbfa8fSPeter Zijlstra if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) 15186470930SIngo Molnar return 1; 15286470930SIngo Molnar 15386470930SIngo Molnar return 0; 15486470930SIngo Molnar } 15586470930SIngo Molnar 15686470930SIngo Molnar /* 15786470930SIngo Molnar * Read out the results of a single counter: 15886470930SIngo Molnar */ 15986470930SIngo Molnar static void read_counter(int counter) 16086470930SIngo Molnar { 16186470930SIngo Molnar __u64 *count, single_count[3]; 16286470930SIngo Molnar ssize_t res; 16386470930SIngo Molnar int cpu, nv; 16486470930SIngo Molnar int scaled; 16586470930SIngo Molnar 16642202dd5SIngo Molnar count = event_res[run_idx][counter]; 16786470930SIngo Molnar 16886470930SIngo Molnar count[0] = count[1] = count[2] = 0; 16986470930SIngo Molnar 17086470930SIngo Molnar nv = scale ? 3 : 1; 17186470930SIngo Molnar for (cpu = 0; cpu < nr_cpus; cpu ++) { 172743ee1f8SIngo Molnar if (fd[cpu][counter] < 0) 173743ee1f8SIngo Molnar continue; 174743ee1f8SIngo Molnar 17586470930SIngo Molnar res = read(fd[cpu][counter], single_count, nv * sizeof(__u64)); 17686470930SIngo Molnar assert(res == nv * sizeof(__u64)); 17742202dd5SIngo Molnar close(fd[cpu][counter]); 17842202dd5SIngo Molnar fd[cpu][counter] = -1; 17986470930SIngo Molnar 18086470930SIngo Molnar count[0] += single_count[0]; 18186470930SIngo Molnar if (scale) { 18286470930SIngo Molnar count[1] += single_count[1]; 18386470930SIngo Molnar count[2] += single_count[2]; 18486470930SIngo Molnar } 18586470930SIngo Molnar } 18686470930SIngo Molnar 18786470930SIngo Molnar scaled = 0; 18886470930SIngo Molnar if (scale) { 18986470930SIngo Molnar if (count[2] == 0) { 19042202dd5SIngo Molnar event_scaled[run_idx][counter] = -1; 19186470930SIngo Molnar count[0] = 0; 19286470930SIngo Molnar return; 19386470930SIngo Molnar } 19486470930SIngo Molnar 19586470930SIngo Molnar if (count[2] < count[1]) { 19642202dd5SIngo Molnar event_scaled[run_idx][counter] = 1; 19786470930SIngo Molnar count[0] = (unsigned long long) 19886470930SIngo Molnar ((double)count[0] * count[1] / count[2] + 0.5); 19986470930SIngo Molnar } 20086470930SIngo Molnar } 20186470930SIngo Molnar /* 20286470930SIngo Molnar * Save the full runtime - to allow normalization during printout: 20386470930SIngo Molnar */ 20486470930SIngo Molnar if (attrs[counter].type == PERF_TYPE_SOFTWARE && 205f4dbfa8fSPeter Zijlstra attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) 20642202dd5SIngo Molnar runtime_nsecs[run_idx] = count[0]; 207e779898aSIngo Molnar if (attrs[counter].type == PERF_TYPE_HARDWARE && 208f4dbfa8fSPeter Zijlstra attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES) 20942202dd5SIngo Molnar runtime_cycles[run_idx] = count[0]; 21086470930SIngo Molnar } 21186470930SIngo Molnar 21242202dd5SIngo Molnar static int run_perf_stat(int argc, const char **argv) 21386470930SIngo Molnar { 21486470930SIngo Molnar unsigned long long t0, t1; 21542202dd5SIngo Molnar int status = 0; 21686470930SIngo Molnar int counter; 21786470930SIngo Molnar int pid; 21886470930SIngo Molnar 21986470930SIngo Molnar if (!system_wide) 22086470930SIngo Molnar nr_cpus = 1; 22186470930SIngo Molnar 22286470930SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 223743ee1f8SIngo Molnar create_perf_stat_counter(counter); 22486470930SIngo Molnar 22586470930SIngo Molnar /* 22686470930SIngo Molnar * Enable counters and exec the command: 22786470930SIngo Molnar */ 22886470930SIngo Molnar t0 = rdclock(); 22986470930SIngo Molnar prctl(PR_TASK_PERF_COUNTERS_ENABLE); 23086470930SIngo Molnar 23186470930SIngo Molnar if ((pid = fork()) < 0) 23286470930SIngo Molnar perror("failed to fork"); 23386470930SIngo Molnar 23486470930SIngo Molnar if (!pid) { 23586470930SIngo Molnar if (execvp(argv[0], (char **)argv)) { 23686470930SIngo Molnar perror(argv[0]); 23786470930SIngo Molnar exit(-1); 23886470930SIngo Molnar } 23986470930SIngo Molnar } 24086470930SIngo Molnar 24142202dd5SIngo Molnar wait(&status); 24286470930SIngo Molnar 24386470930SIngo Molnar prctl(PR_TASK_PERF_COUNTERS_DISABLE); 24486470930SIngo Molnar t1 = rdclock(); 24586470930SIngo Molnar 24642202dd5SIngo Molnar walltime_nsecs[run_idx] = t1 - t0; 24742202dd5SIngo Molnar 24842202dd5SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 24942202dd5SIngo Molnar read_counter(counter); 25042202dd5SIngo Molnar 25142202dd5SIngo Molnar return WEXITSTATUS(status); 25242202dd5SIngo Molnar } 25342202dd5SIngo Molnar 25442202dd5SIngo Molnar static void print_noise(__u64 *count, __u64 *noise) 25542202dd5SIngo Molnar { 25642202dd5SIngo Molnar if (run_count > 1) 25742202dd5SIngo Molnar fprintf(stderr, " ( +- %7.3f%% )", 25842202dd5SIngo Molnar (double)noise[0]/(count[0]+1)*100.0); 25942202dd5SIngo Molnar } 26042202dd5SIngo Molnar 26142202dd5SIngo Molnar static void nsec_printout(int counter, __u64 *count, __u64 *noise) 26242202dd5SIngo Molnar { 26342202dd5SIngo Molnar double msecs = (double)count[0] / 1000000; 26442202dd5SIngo Molnar 26542202dd5SIngo Molnar fprintf(stderr, " %14.6f %-20s", msecs, event_name(counter)); 26642202dd5SIngo Molnar 26742202dd5SIngo Molnar if (attrs[counter].type == PERF_TYPE_SOFTWARE && 26842202dd5SIngo Molnar attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) { 26942202dd5SIngo Molnar 27042202dd5SIngo Molnar if (walltime_nsecs_avg) 27142202dd5SIngo Molnar fprintf(stderr, " # %10.3f CPUs ", 27242202dd5SIngo Molnar (double)count[0] / (double)walltime_nsecs_avg); 27342202dd5SIngo Molnar } 27442202dd5SIngo Molnar print_noise(count, noise); 27542202dd5SIngo Molnar } 27642202dd5SIngo Molnar 27742202dd5SIngo Molnar static void abs_printout(int counter, __u64 *count, __u64 *noise) 27842202dd5SIngo Molnar { 27942202dd5SIngo Molnar fprintf(stderr, " %14Ld %-20s", count[0], event_name(counter)); 28042202dd5SIngo Molnar 28142202dd5SIngo Molnar if (runtime_cycles_avg && 28242202dd5SIngo Molnar attrs[counter].type == PERF_TYPE_HARDWARE && 28342202dd5SIngo Molnar attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) { 28442202dd5SIngo Molnar 28542202dd5SIngo Molnar fprintf(stderr, " # %10.3f IPC ", 28642202dd5SIngo Molnar (double)count[0] / (double)runtime_cycles_avg); 28742202dd5SIngo Molnar } else { 28842202dd5SIngo Molnar if (runtime_nsecs_avg) { 28942202dd5SIngo Molnar fprintf(stderr, " # %10.3f M/sec", 29042202dd5SIngo Molnar (double)count[0]/runtime_nsecs_avg*1000.0); 29142202dd5SIngo Molnar } 29242202dd5SIngo Molnar } 29342202dd5SIngo Molnar print_noise(count, noise); 29442202dd5SIngo Molnar } 29542202dd5SIngo Molnar 29642202dd5SIngo Molnar /* 29742202dd5SIngo Molnar * Print out the results of a single counter: 29842202dd5SIngo Molnar */ 29942202dd5SIngo Molnar static void print_counter(int counter) 30042202dd5SIngo Molnar { 30142202dd5SIngo Molnar __u64 *count, *noise; 30242202dd5SIngo Molnar int scaled; 30342202dd5SIngo Molnar 30442202dd5SIngo Molnar count = event_res_avg[counter]; 30542202dd5SIngo Molnar noise = event_res_noise[counter]; 30642202dd5SIngo Molnar scaled = event_scaled_avg[counter]; 30742202dd5SIngo Molnar 30842202dd5SIngo Molnar if (scaled == -1) { 30942202dd5SIngo Molnar fprintf(stderr, " %14s %-20s\n", 31042202dd5SIngo Molnar "<not counted>", event_name(counter)); 31142202dd5SIngo Molnar return; 31242202dd5SIngo Molnar } 31342202dd5SIngo Molnar 31442202dd5SIngo Molnar if (nsec_counter(counter)) 31542202dd5SIngo Molnar nsec_printout(counter, count, noise); 31642202dd5SIngo Molnar else 31742202dd5SIngo Molnar abs_printout(counter, count, noise); 31842202dd5SIngo Molnar 31942202dd5SIngo Molnar if (scaled) 32042202dd5SIngo Molnar fprintf(stderr, " (scaled from %.2f%%)", 32142202dd5SIngo Molnar (double) count[2] / count[1] * 100); 32242202dd5SIngo Molnar 32342202dd5SIngo Molnar fprintf(stderr, "\n"); 32442202dd5SIngo Molnar } 32542202dd5SIngo Molnar 32642202dd5SIngo Molnar /* 327ef281a19SIngo Molnar * normalize_noise noise values down to stddev: 32842202dd5SIngo Molnar */ 329ef281a19SIngo Molnar static void normalize_noise(__u64 *val) 33042202dd5SIngo Molnar { 33142202dd5SIngo Molnar double res; 33242202dd5SIngo Molnar 33342202dd5SIngo Molnar res = (double)*val / (run_count * sqrt((double)run_count)); 33442202dd5SIngo Molnar 33542202dd5SIngo Molnar *val = (__u64)res; 33642202dd5SIngo Molnar } 33742202dd5SIngo Molnar 338ef281a19SIngo Molnar static void update_avg(const char *name, int idx, __u64 *avg, __u64 *val) 339ef281a19SIngo Molnar { 340ef281a19SIngo Molnar *avg += *val; 341ef281a19SIngo Molnar 342ef281a19SIngo Molnar if (verbose > 1) 343ef281a19SIngo Molnar fprintf(stderr, "debug: %20s[%d]: %Ld\n", name, idx, *val); 344ef281a19SIngo Molnar } 34542202dd5SIngo Molnar /* 34642202dd5SIngo Molnar * Calculate the averages and noises: 34742202dd5SIngo Molnar */ 34842202dd5SIngo Molnar static void calc_avg(void) 34942202dd5SIngo Molnar { 35042202dd5SIngo Molnar int i, j; 35142202dd5SIngo Molnar 352ef281a19SIngo Molnar if (verbose > 1) 353ef281a19SIngo Molnar fprintf(stderr, "\n"); 354ef281a19SIngo Molnar 35542202dd5SIngo Molnar for (i = 0; i < run_count; i++) { 356ef281a19SIngo Molnar update_avg("runtime", 0, &runtime_nsecs_avg, runtime_nsecs + i); 357ef281a19SIngo Molnar update_avg("walltime", 0, &walltime_nsecs_avg, walltime_nsecs + i); 358ef281a19SIngo Molnar update_avg("runtime_cycles", 0, &runtime_cycles_avg, runtime_cycles + i); 35942202dd5SIngo Molnar 36042202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 361ef281a19SIngo Molnar update_avg("counter/0", j, 362ef281a19SIngo Molnar event_res_avg[j]+0, event_res[i][j]+0); 363ef281a19SIngo Molnar update_avg("counter/1", j, 364ef281a19SIngo Molnar event_res_avg[j]+1, event_res[i][j]+1); 365ef281a19SIngo Molnar update_avg("counter/2", j, 366ef281a19SIngo Molnar event_res_avg[j]+2, event_res[i][j]+2); 367ef281a19SIngo Molnar update_avg("scaled", j, 368ef281a19SIngo Molnar event_scaled_avg + j, event_scaled[i]+j); 36942202dd5SIngo Molnar } 37042202dd5SIngo Molnar } 37142202dd5SIngo Molnar runtime_nsecs_avg /= run_count; 37242202dd5SIngo Molnar walltime_nsecs_avg /= run_count; 37342202dd5SIngo Molnar runtime_cycles_avg /= run_count; 37442202dd5SIngo Molnar 37542202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 37642202dd5SIngo Molnar event_res_avg[j][0] /= run_count; 37742202dd5SIngo Molnar event_res_avg[j][1] /= run_count; 37842202dd5SIngo Molnar event_res_avg[j][2] /= run_count; 37942202dd5SIngo Molnar } 38042202dd5SIngo Molnar 38142202dd5SIngo Molnar for (i = 0; i < run_count; i++) { 38242202dd5SIngo Molnar runtime_nsecs_noise += 38342202dd5SIngo Molnar abs((__s64)(runtime_nsecs[i] - runtime_nsecs_avg)); 38442202dd5SIngo Molnar walltime_nsecs_noise += 38542202dd5SIngo Molnar abs((__s64)(walltime_nsecs[i] - walltime_nsecs_avg)); 38642202dd5SIngo Molnar runtime_cycles_noise += 38742202dd5SIngo Molnar abs((__s64)(runtime_cycles[i] - runtime_cycles_avg)); 38842202dd5SIngo Molnar 38942202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 39042202dd5SIngo Molnar event_res_noise[j][0] += 39142202dd5SIngo Molnar abs((__s64)(event_res[i][j][0] - event_res_avg[j][0])); 39242202dd5SIngo Molnar event_res_noise[j][1] += 39342202dd5SIngo Molnar abs((__s64)(event_res[i][j][1] - event_res_avg[j][1])); 39442202dd5SIngo Molnar event_res_noise[j][2] += 39542202dd5SIngo Molnar abs((__s64)(event_res[i][j][2] - event_res_avg[j][2])); 39642202dd5SIngo Molnar } 39742202dd5SIngo Molnar } 39842202dd5SIngo Molnar 399ef281a19SIngo Molnar normalize_noise(&runtime_nsecs_noise); 400ef281a19SIngo Molnar normalize_noise(&walltime_nsecs_noise); 401ef281a19SIngo Molnar normalize_noise(&runtime_cycles_noise); 40242202dd5SIngo Molnar 40342202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 404ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][0]); 405ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][1]); 406ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][2]); 40742202dd5SIngo Molnar } 40842202dd5SIngo Molnar } 40942202dd5SIngo Molnar 41042202dd5SIngo Molnar static void print_stat(int argc, const char **argv) 41142202dd5SIngo Molnar { 41242202dd5SIngo Molnar int i, counter; 41342202dd5SIngo Molnar 41442202dd5SIngo Molnar calc_avg(); 41542202dd5SIngo Molnar 41686470930SIngo Molnar fflush(stdout); 41786470930SIngo Molnar 41886470930SIngo Molnar fprintf(stderr, "\n"); 41986470930SIngo Molnar fprintf(stderr, " Performance counter stats for \'%s", argv[0]); 42086470930SIngo Molnar 42186470930SIngo Molnar for (i = 1; i < argc; i++) 42286470930SIngo Molnar fprintf(stderr, " %s", argv[i]); 42386470930SIngo Molnar 42442202dd5SIngo Molnar fprintf(stderr, "\'"); 42542202dd5SIngo Molnar if (run_count > 1) 42642202dd5SIngo Molnar fprintf(stderr, " (%d runs)", run_count); 42742202dd5SIngo Molnar fprintf(stderr, ":\n\n"); 42886470930SIngo Molnar 42986470930SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 43086470930SIngo Molnar print_counter(counter); 43186470930SIngo Molnar 43286470930SIngo Molnar 43386470930SIngo Molnar fprintf(stderr, "\n"); 43442202dd5SIngo Molnar fprintf(stderr, " %14.9f seconds time elapsed.\n", 43542202dd5SIngo Molnar (double)walltime_nsecs_avg/1e9); 43686470930SIngo Molnar fprintf(stderr, "\n"); 43786470930SIngo Molnar } 43886470930SIngo Molnar 439f7b7c26eSPeter Zijlstra static volatile int signr = -1; 440f7b7c26eSPeter Zijlstra 44186470930SIngo Molnar static void skip_signal(int signo) 44286470930SIngo Molnar { 443f7b7c26eSPeter Zijlstra signr = signo; 444f7b7c26eSPeter Zijlstra } 445f7b7c26eSPeter Zijlstra 446f7b7c26eSPeter Zijlstra static void sig_atexit(void) 447f7b7c26eSPeter Zijlstra { 448f7b7c26eSPeter Zijlstra if (signr == -1) 449f7b7c26eSPeter Zijlstra return; 450f7b7c26eSPeter Zijlstra 451f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 452f7b7c26eSPeter Zijlstra kill(getpid(), signr); 45386470930SIngo Molnar } 45486470930SIngo Molnar 45586470930SIngo Molnar static const char * const stat_usage[] = { 45686470930SIngo Molnar "perf stat [<options>] <command>", 45786470930SIngo Molnar NULL 45886470930SIngo Molnar }; 45986470930SIngo Molnar 46086470930SIngo Molnar static const struct option options[] = { 46186470930SIngo Molnar OPT_CALLBACK('e', "event", NULL, "event", 46286470930SIngo Molnar "event selector. use 'perf list' to list available events", 46386470930SIngo Molnar parse_events), 46486470930SIngo Molnar OPT_BOOLEAN('i', "inherit", &inherit, 46586470930SIngo Molnar "child tasks inherit counters"), 46686470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 46786470930SIngo Molnar "stat events on existing pid"), 46886470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 46986470930SIngo Molnar "system-wide collection from all CPUs"), 47086470930SIngo Molnar OPT_BOOLEAN('S', "scale", &scale, 47186470930SIngo Molnar "scale/normalize counters"), 472743ee1f8SIngo Molnar OPT_BOOLEAN('v', "verbose", &verbose, 473743ee1f8SIngo Molnar "be more verbose (show counter open errors, etc)"), 47442202dd5SIngo Molnar OPT_INTEGER('r', "repeat", &run_count, 47542202dd5SIngo Molnar "repeat command and print average + stddev (max: 100)"), 47686470930SIngo Molnar OPT_END() 47786470930SIngo Molnar }; 47886470930SIngo Molnar 47986470930SIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix) 48086470930SIngo Molnar { 48142202dd5SIngo Molnar int status; 48242202dd5SIngo Molnar 48386470930SIngo Molnar page_size = sysconf(_SC_PAGE_SIZE); 48486470930SIngo Molnar 48586470930SIngo Molnar memcpy(attrs, default_attrs, sizeof(attrs)); 48686470930SIngo Molnar 48786470930SIngo Molnar argc = parse_options(argc, argv, options, stat_usage, 0); 48886470930SIngo Molnar if (!argc) 48986470930SIngo Molnar usage_with_options(stat_usage, options); 49042202dd5SIngo Molnar if (run_count <= 0 || run_count > MAX_RUN) 49142202dd5SIngo Molnar usage_with_options(stat_usage, options); 49286470930SIngo Molnar 49386470930SIngo Molnar if (!nr_counters) 49486470930SIngo Molnar nr_counters = 8; 49586470930SIngo Molnar 49686470930SIngo Molnar nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 49786470930SIngo Molnar assert(nr_cpus <= MAX_NR_CPUS); 49886470930SIngo Molnar assert(nr_cpus >= 0); 49986470930SIngo Molnar 50086470930SIngo Molnar /* 50186470930SIngo Molnar * We dont want to block the signals - that would cause 50286470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 50386470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 50486470930SIngo Molnar * task, but being ignored by perf stat itself: 50586470930SIngo Molnar */ 506f7b7c26eSPeter Zijlstra atexit(sig_atexit); 50786470930SIngo Molnar signal(SIGINT, skip_signal); 50886470930SIngo Molnar signal(SIGALRM, skip_signal); 50986470930SIngo Molnar signal(SIGABRT, skip_signal); 51086470930SIngo Molnar 51142202dd5SIngo Molnar status = 0; 51242202dd5SIngo Molnar for (run_idx = 0; run_idx < run_count; run_idx++) { 51342202dd5SIngo Molnar if (run_count != 1 && verbose) 51442202dd5SIngo Molnar fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx+1); 51542202dd5SIngo Molnar status = run_perf_stat(argc, argv); 51642202dd5SIngo Molnar } 51742202dd5SIngo Molnar 51842202dd5SIngo Molnar print_stat(argc, argv); 51942202dd5SIngo Molnar 52042202dd5SIngo Molnar return status; 52186470930SIngo Molnar } 522