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; 673d632595SJaswinder Singh Rajput static 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 99cca03c0aSJaswinder Singh Rajput #define ERR_PERF_OPEN \ 100cca03c0aSJaswinder Singh Rajput "Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" 101cca03c0aSJaswinder Singh Rajput 102743ee1f8SIngo Molnar static void create_perf_stat_counter(int counter) 10386470930SIngo Molnar { 10486470930SIngo Molnar struct perf_counter_attr *attr = attrs + counter; 10586470930SIngo Molnar 10686470930SIngo Molnar if (scale) 10786470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 10886470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 10986470930SIngo Molnar 11086470930SIngo Molnar if (system_wide) { 11186470930SIngo Molnar int cpu; 11286470930SIngo Molnar for (cpu = 0; cpu < nr_cpus; cpu++) { 11386470930SIngo Molnar fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); 114cca03c0aSJaswinder Singh Rajput if (fd[cpu][counter] < 0 && verbose) 115cca03c0aSJaswinder Singh Rajput fprintf(stderr, ERR_PERF_OPEN, counter, 116cca03c0aSJaswinder Singh Rajput fd[cpu][counter], strerror(errno)); 11786470930SIngo Molnar } 11886470930SIngo Molnar } else { 11986470930SIngo Molnar attr->inherit = inherit; 12086470930SIngo Molnar attr->disabled = 1; 12186470930SIngo Molnar 12286470930SIngo Molnar fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0); 123cca03c0aSJaswinder Singh Rajput if (fd[0][counter] < 0 && verbose) 124cca03c0aSJaswinder Singh Rajput fprintf(stderr, ERR_PERF_OPEN, counter, 125cca03c0aSJaswinder Singh Rajput fd[0][counter], strerror(errno)); 12686470930SIngo Molnar } 12786470930SIngo Molnar } 12886470930SIngo Molnar 12986470930SIngo Molnar /* 13086470930SIngo Molnar * Does the counter have nsecs as a unit? 13186470930SIngo Molnar */ 13286470930SIngo Molnar static inline int nsec_counter(int counter) 13386470930SIngo Molnar { 13486470930SIngo Molnar if (attrs[counter].type != PERF_TYPE_SOFTWARE) 13586470930SIngo Molnar return 0; 13686470930SIngo Molnar 137f4dbfa8fSPeter Zijlstra if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK) 13886470930SIngo Molnar return 1; 13986470930SIngo Molnar 140f4dbfa8fSPeter Zijlstra if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) 14186470930SIngo Molnar return 1; 14286470930SIngo Molnar 14386470930SIngo Molnar return 0; 14486470930SIngo Molnar } 14586470930SIngo Molnar 14686470930SIngo Molnar /* 14786470930SIngo Molnar * Read out the results of a single counter: 14886470930SIngo Molnar */ 14986470930SIngo Molnar static void read_counter(int counter) 15086470930SIngo Molnar { 1519cffa8d5SPaul Mackerras u64 *count, single_count[3]; 15286470930SIngo Molnar ssize_t res; 15386470930SIngo Molnar int cpu, nv; 15486470930SIngo Molnar int scaled; 15586470930SIngo Molnar 15642202dd5SIngo Molnar count = event_res[run_idx][counter]; 15786470930SIngo Molnar 15886470930SIngo Molnar count[0] = count[1] = count[2] = 0; 15986470930SIngo Molnar 16086470930SIngo Molnar nv = scale ? 3 : 1; 16186470930SIngo Molnar for (cpu = 0; cpu < nr_cpus; cpu++) { 162743ee1f8SIngo Molnar if (fd[cpu][counter] < 0) 163743ee1f8SIngo Molnar continue; 164743ee1f8SIngo Molnar 1659cffa8d5SPaul Mackerras res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); 1669cffa8d5SPaul Mackerras assert(res == nv * sizeof(u64)); 16742202dd5SIngo Molnar close(fd[cpu][counter]); 16842202dd5SIngo Molnar fd[cpu][counter] = -1; 16986470930SIngo Molnar 17086470930SIngo Molnar count[0] += single_count[0]; 17186470930SIngo Molnar if (scale) { 17286470930SIngo Molnar count[1] += single_count[1]; 17386470930SIngo Molnar count[2] += single_count[2]; 17486470930SIngo Molnar } 17586470930SIngo Molnar } 17686470930SIngo Molnar 17786470930SIngo Molnar scaled = 0; 17886470930SIngo Molnar if (scale) { 17986470930SIngo Molnar if (count[2] == 0) { 18042202dd5SIngo Molnar event_scaled[run_idx][counter] = -1; 18186470930SIngo Molnar count[0] = 0; 18286470930SIngo Molnar return; 18386470930SIngo Molnar } 18486470930SIngo Molnar 18586470930SIngo Molnar if (count[2] < count[1]) { 18642202dd5SIngo Molnar event_scaled[run_idx][counter] = 1; 18786470930SIngo Molnar count[0] = (unsigned long long) 18886470930SIngo Molnar ((double)count[0] * count[1] / count[2] + 0.5); 18986470930SIngo Molnar } 19086470930SIngo Molnar } 19186470930SIngo Molnar /* 19286470930SIngo Molnar * Save the full runtime - to allow normalization during printout: 19386470930SIngo Molnar */ 19486470930SIngo Molnar if (attrs[counter].type == PERF_TYPE_SOFTWARE && 195f4dbfa8fSPeter Zijlstra attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) 19642202dd5SIngo Molnar runtime_nsecs[run_idx] = count[0]; 197e779898aSIngo Molnar if (attrs[counter].type == PERF_TYPE_HARDWARE && 198f4dbfa8fSPeter Zijlstra attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES) 19942202dd5SIngo Molnar runtime_cycles[run_idx] = count[0]; 20086470930SIngo Molnar } 20186470930SIngo Molnar 20242202dd5SIngo Molnar static int run_perf_stat(int argc, 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; 20886470930SIngo Molnar 20986470930SIngo Molnar if (!system_wide) 21086470930SIngo Molnar nr_cpus = 1; 21186470930SIngo Molnar 21286470930SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 213743ee1f8SIngo Molnar create_perf_stat_counter(counter); 21486470930SIngo Molnar 21586470930SIngo Molnar /* 21686470930SIngo Molnar * Enable counters and exec the command: 21786470930SIngo Molnar */ 21886470930SIngo Molnar t0 = rdclock(); 21986470930SIngo Molnar prctl(PR_TASK_PERF_COUNTERS_ENABLE); 22086470930SIngo Molnar 22186470930SIngo Molnar if ((pid = fork()) < 0) 22286470930SIngo Molnar perror("failed to fork"); 22386470930SIngo Molnar 22486470930SIngo Molnar if (!pid) { 22586470930SIngo Molnar if (execvp(argv[0], (char **)argv)) { 22686470930SIngo Molnar perror(argv[0]); 22786470930SIngo Molnar exit(-1); 22886470930SIngo Molnar } 22986470930SIngo Molnar } 23086470930SIngo Molnar 23142202dd5SIngo Molnar wait(&status); 23286470930SIngo Molnar 23386470930SIngo Molnar prctl(PR_TASK_PERF_COUNTERS_DISABLE); 23486470930SIngo Molnar t1 = rdclock(); 23586470930SIngo Molnar 23642202dd5SIngo Molnar walltime_nsecs[run_idx] = t1 - t0; 23742202dd5SIngo Molnar 23842202dd5SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 23942202dd5SIngo Molnar read_counter(counter); 24042202dd5SIngo Molnar 24142202dd5SIngo Molnar return WEXITSTATUS(status); 24242202dd5SIngo Molnar } 24342202dd5SIngo Molnar 2449cffa8d5SPaul Mackerras static void print_noise(u64 *count, u64 *noise) 24542202dd5SIngo Molnar { 24642202dd5SIngo Molnar if (run_count > 1) 24742202dd5SIngo Molnar fprintf(stderr, " ( +- %7.3f%% )", 24842202dd5SIngo Molnar (double)noise[0]/(count[0]+1)*100.0); 24942202dd5SIngo Molnar } 25042202dd5SIngo Molnar 2519cffa8d5SPaul Mackerras static void nsec_printout(int counter, u64 *count, u64 *noise) 25242202dd5SIngo Molnar { 25342202dd5SIngo Molnar double msecs = (double)count[0] / 1000000; 25442202dd5SIngo Molnar 2556e750a8fSJaswinder Singh Rajput fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); 25642202dd5SIngo Molnar 25742202dd5SIngo Molnar if (attrs[counter].type == PERF_TYPE_SOFTWARE && 25842202dd5SIngo Molnar attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) { 25942202dd5SIngo Molnar 26042202dd5SIngo Molnar if (walltime_nsecs_avg) 26142202dd5SIngo Molnar fprintf(stderr, " # %10.3f CPUs ", 26242202dd5SIngo Molnar (double)count[0] / (double)walltime_nsecs_avg); 26342202dd5SIngo Molnar } 26442202dd5SIngo Molnar print_noise(count, noise); 26542202dd5SIngo Molnar } 26642202dd5SIngo Molnar 2679cffa8d5SPaul Mackerras static void abs_printout(int counter, u64 *count, u64 *noise) 26842202dd5SIngo Molnar { 2696e750a8fSJaswinder Singh Rajput fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter)); 27042202dd5SIngo Molnar 27142202dd5SIngo Molnar if (runtime_cycles_avg && 27242202dd5SIngo Molnar attrs[counter].type == PERF_TYPE_HARDWARE && 27342202dd5SIngo Molnar attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) { 27442202dd5SIngo Molnar 27542202dd5SIngo Molnar fprintf(stderr, " # %10.3f IPC ", 27642202dd5SIngo Molnar (double)count[0] / (double)runtime_cycles_avg); 27742202dd5SIngo Molnar } else { 27842202dd5SIngo Molnar if (runtime_nsecs_avg) { 27942202dd5SIngo Molnar fprintf(stderr, " # %10.3f M/sec", 28042202dd5SIngo Molnar (double)count[0]/runtime_nsecs_avg*1000.0); 28142202dd5SIngo Molnar } 28242202dd5SIngo Molnar } 28342202dd5SIngo Molnar print_noise(count, noise); 28442202dd5SIngo Molnar } 28542202dd5SIngo Molnar 28642202dd5SIngo Molnar /* 28742202dd5SIngo Molnar * Print out the results of a single counter: 28842202dd5SIngo Molnar */ 28942202dd5SIngo Molnar static void print_counter(int counter) 29042202dd5SIngo Molnar { 2919cffa8d5SPaul Mackerras u64 *count, *noise; 29242202dd5SIngo Molnar int scaled; 29342202dd5SIngo Molnar 29442202dd5SIngo Molnar count = event_res_avg[counter]; 29542202dd5SIngo Molnar noise = event_res_noise[counter]; 29642202dd5SIngo Molnar scaled = event_scaled_avg[counter]; 29742202dd5SIngo Molnar 29842202dd5SIngo Molnar if (scaled == -1) { 2996e750a8fSJaswinder Singh Rajput fprintf(stderr, " %14s %-24s\n", 30042202dd5SIngo Molnar "<not counted>", event_name(counter)); 30142202dd5SIngo Molnar return; 30242202dd5SIngo Molnar } 30342202dd5SIngo Molnar 30442202dd5SIngo Molnar if (nsec_counter(counter)) 30542202dd5SIngo Molnar nsec_printout(counter, count, noise); 30642202dd5SIngo Molnar else 30742202dd5SIngo Molnar abs_printout(counter, count, noise); 30842202dd5SIngo Molnar 30942202dd5SIngo Molnar if (scaled) 3106e750a8fSJaswinder Singh Rajput fprintf(stderr, " (%7.2fx scaled)", (double)count[1]/count[2]); 31142202dd5SIngo Molnar 31242202dd5SIngo Molnar fprintf(stderr, "\n"); 31342202dd5SIngo Molnar } 31442202dd5SIngo Molnar 31542202dd5SIngo Molnar /* 316ef281a19SIngo Molnar * normalize_noise noise values down to stddev: 31742202dd5SIngo Molnar */ 3189cffa8d5SPaul Mackerras static void normalize_noise(u64 *val) 31942202dd5SIngo Molnar { 32042202dd5SIngo Molnar double res; 32142202dd5SIngo Molnar 32242202dd5SIngo Molnar res = (double)*val / (run_count * sqrt((double)run_count)); 32342202dd5SIngo Molnar 3249cffa8d5SPaul Mackerras *val = (u64)res; 32542202dd5SIngo Molnar } 32642202dd5SIngo Molnar 3279cffa8d5SPaul Mackerras static void update_avg(const char *name, int idx, u64 *avg, u64 *val) 328ef281a19SIngo Molnar { 329ef281a19SIngo Molnar *avg += *val; 330ef281a19SIngo Molnar 331ef281a19SIngo Molnar if (verbose > 1) 332ef281a19SIngo Molnar fprintf(stderr, "debug: %20s[%d]: %Ld\n", name, idx, *val); 333ef281a19SIngo Molnar } 33442202dd5SIngo Molnar /* 33542202dd5SIngo Molnar * Calculate the averages and noises: 33642202dd5SIngo Molnar */ 33742202dd5SIngo Molnar static void calc_avg(void) 33842202dd5SIngo Molnar { 33942202dd5SIngo Molnar int i, j; 34042202dd5SIngo Molnar 341ef281a19SIngo Molnar if (verbose > 1) 342ef281a19SIngo Molnar fprintf(stderr, "\n"); 343ef281a19SIngo Molnar 34442202dd5SIngo Molnar for (i = 0; i < run_count; i++) { 345ef281a19SIngo Molnar update_avg("runtime", 0, &runtime_nsecs_avg, runtime_nsecs + i); 346ef281a19SIngo Molnar update_avg("walltime", 0, &walltime_nsecs_avg, walltime_nsecs + i); 347ef281a19SIngo Molnar update_avg("runtime_cycles", 0, &runtime_cycles_avg, runtime_cycles + i); 34842202dd5SIngo Molnar 34942202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 350ef281a19SIngo Molnar update_avg("counter/0", j, 351ef281a19SIngo Molnar event_res_avg[j]+0, event_res[i][j]+0); 352ef281a19SIngo Molnar update_avg("counter/1", j, 353ef281a19SIngo Molnar event_res_avg[j]+1, event_res[i][j]+1); 354ef281a19SIngo Molnar update_avg("counter/2", j, 355ef281a19SIngo Molnar event_res_avg[j]+2, event_res[i][j]+2); 356566747e6SIngo Molnar if (event_scaled[i][j] != -1) 357ef281a19SIngo Molnar update_avg("scaled", j, 358ef281a19SIngo Molnar event_scaled_avg + j, event_scaled[i]+j); 359566747e6SIngo Molnar else 360566747e6SIngo Molnar event_scaled_avg[j] = -1; 36142202dd5SIngo Molnar } 36242202dd5SIngo Molnar } 36342202dd5SIngo Molnar runtime_nsecs_avg /= run_count; 36442202dd5SIngo Molnar walltime_nsecs_avg /= run_count; 36542202dd5SIngo Molnar runtime_cycles_avg /= run_count; 36642202dd5SIngo Molnar 36742202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 36842202dd5SIngo Molnar event_res_avg[j][0] /= run_count; 36942202dd5SIngo Molnar event_res_avg[j][1] /= run_count; 37042202dd5SIngo Molnar event_res_avg[j][2] /= run_count; 37142202dd5SIngo Molnar } 37242202dd5SIngo Molnar 37342202dd5SIngo Molnar for (i = 0; i < run_count; i++) { 37442202dd5SIngo Molnar runtime_nsecs_noise += 3759cffa8d5SPaul Mackerras abs((s64)(runtime_nsecs[i] - runtime_nsecs_avg)); 37642202dd5SIngo Molnar walltime_nsecs_noise += 3779cffa8d5SPaul Mackerras abs((s64)(walltime_nsecs[i] - walltime_nsecs_avg)); 37842202dd5SIngo Molnar runtime_cycles_noise += 3799cffa8d5SPaul Mackerras abs((s64)(runtime_cycles[i] - runtime_cycles_avg)); 38042202dd5SIngo Molnar 38142202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 38242202dd5SIngo Molnar event_res_noise[j][0] += 3839cffa8d5SPaul Mackerras abs((s64)(event_res[i][j][0] - event_res_avg[j][0])); 38442202dd5SIngo Molnar event_res_noise[j][1] += 3859cffa8d5SPaul Mackerras abs((s64)(event_res[i][j][1] - event_res_avg[j][1])); 38642202dd5SIngo Molnar event_res_noise[j][2] += 3879cffa8d5SPaul Mackerras abs((s64)(event_res[i][j][2] - event_res_avg[j][2])); 38842202dd5SIngo Molnar } 38942202dd5SIngo Molnar } 39042202dd5SIngo Molnar 391ef281a19SIngo Molnar normalize_noise(&runtime_nsecs_noise); 392ef281a19SIngo Molnar normalize_noise(&walltime_nsecs_noise); 393ef281a19SIngo Molnar normalize_noise(&runtime_cycles_noise); 39442202dd5SIngo Molnar 39542202dd5SIngo Molnar for (j = 0; j < nr_counters; j++) { 396ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][0]); 397ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][1]); 398ef281a19SIngo Molnar normalize_noise(&event_res_noise[j][2]); 39942202dd5SIngo Molnar } 40042202dd5SIngo Molnar } 40142202dd5SIngo Molnar 40242202dd5SIngo Molnar static void print_stat(int argc, const char **argv) 40342202dd5SIngo Molnar { 40442202dd5SIngo Molnar int i, counter; 40542202dd5SIngo Molnar 40642202dd5SIngo Molnar calc_avg(); 40742202dd5SIngo Molnar 40886470930SIngo Molnar fflush(stdout); 40986470930SIngo Molnar 41086470930SIngo Molnar fprintf(stderr, "\n"); 41186470930SIngo Molnar fprintf(stderr, " Performance counter stats for \'%s", argv[0]); 41286470930SIngo Molnar 41386470930SIngo Molnar for (i = 1; i < argc; i++) 41486470930SIngo Molnar fprintf(stderr, " %s", argv[i]); 41586470930SIngo Molnar 41642202dd5SIngo Molnar fprintf(stderr, "\'"); 41742202dd5SIngo Molnar if (run_count > 1) 41842202dd5SIngo Molnar fprintf(stderr, " (%d runs)", run_count); 41942202dd5SIngo Molnar fprintf(stderr, ":\n\n"); 42086470930SIngo Molnar 42186470930SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 42286470930SIngo Molnar print_counter(counter); 42386470930SIngo Molnar 42486470930SIngo Molnar fprintf(stderr, "\n"); 425566747e6SIngo Molnar fprintf(stderr, " %14.9f seconds time elapsed", 42642202dd5SIngo Molnar (double)walltime_nsecs_avg/1e9); 427566747e6SIngo Molnar if (run_count > 1) { 428566747e6SIngo Molnar fprintf(stderr, " ( +- %7.3f%% )", 429566747e6SIngo Molnar 100.0*(double)walltime_nsecs_noise/(double)walltime_nsecs_avg); 430566747e6SIngo Molnar } 431566747e6SIngo Molnar fprintf(stderr, "\n\n"); 43286470930SIngo Molnar } 43386470930SIngo Molnar 434f7b7c26eSPeter Zijlstra static volatile int signr = -1; 435f7b7c26eSPeter Zijlstra 43686470930SIngo Molnar static void skip_signal(int signo) 43786470930SIngo Molnar { 438f7b7c26eSPeter Zijlstra signr = signo; 439f7b7c26eSPeter Zijlstra } 440f7b7c26eSPeter Zijlstra 441f7b7c26eSPeter Zijlstra static void sig_atexit(void) 442f7b7c26eSPeter Zijlstra { 443f7b7c26eSPeter Zijlstra if (signr == -1) 444f7b7c26eSPeter Zijlstra return; 445f7b7c26eSPeter Zijlstra 446f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 447f7b7c26eSPeter Zijlstra kill(getpid(), signr); 44886470930SIngo Molnar } 44986470930SIngo Molnar 45086470930SIngo Molnar static const char * const stat_usage[] = { 45186470930SIngo Molnar "perf stat [<options>] <command>", 45286470930SIngo Molnar NULL 45386470930SIngo Molnar }; 45486470930SIngo Molnar 45586470930SIngo Molnar static const struct option options[] = { 45686470930SIngo Molnar OPT_CALLBACK('e', "event", NULL, "event", 45786470930SIngo Molnar "event selector. use 'perf list' to list available events", 45886470930SIngo Molnar parse_events), 45986470930SIngo Molnar OPT_BOOLEAN('i', "inherit", &inherit, 46086470930SIngo Molnar "child tasks inherit counters"), 46186470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 46286470930SIngo Molnar "stat events on existing pid"), 46386470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 46486470930SIngo Molnar "system-wide collection from all CPUs"), 46586470930SIngo Molnar OPT_BOOLEAN('S', "scale", &scale, 46686470930SIngo Molnar "scale/normalize counters"), 467743ee1f8SIngo Molnar OPT_BOOLEAN('v', "verbose", &verbose, 468743ee1f8SIngo Molnar "be more verbose (show counter open errors, etc)"), 46942202dd5SIngo Molnar OPT_INTEGER('r', "repeat", &run_count, 47042202dd5SIngo Molnar "repeat command and print average + stddev (max: 100)"), 4710cfb7a13SIngo Molnar OPT_BOOLEAN('n', "null", &null_run, 4720cfb7a13SIngo Molnar "null run - dont start any counters"), 47386470930SIngo Molnar OPT_END() 47486470930SIngo Molnar }; 47586470930SIngo Molnar 47686470930SIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix) 47786470930SIngo Molnar { 47842202dd5SIngo Molnar int status; 47942202dd5SIngo Molnar 48086470930SIngo Molnar argc = parse_options(argc, argv, options, stat_usage, 0); 48186470930SIngo Molnar if (!argc) 48286470930SIngo Molnar usage_with_options(stat_usage, options); 48342202dd5SIngo Molnar if (run_count <= 0 || run_count > MAX_RUN) 48442202dd5SIngo Molnar usage_with_options(stat_usage, options); 48586470930SIngo Molnar 486c3043569SJaswinder Singh Rajput /* Set attrs and nr_counters if no event is selected and !null_run */ 487c3043569SJaswinder Singh Rajput if (!null_run && !nr_counters) { 488c3043569SJaswinder Singh Rajput memcpy(attrs, default_attrs, sizeof(default_attrs)); 489c3043569SJaswinder Singh Rajput nr_counters = ARRAY_SIZE(default_attrs); 490c3043569SJaswinder Singh Rajput } 49186470930SIngo Molnar 49286470930SIngo Molnar nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 49386470930SIngo Molnar assert(nr_cpus <= MAX_NR_CPUS); 49486470930SIngo Molnar assert(nr_cpus >= 0); 49586470930SIngo Molnar 49686470930SIngo Molnar /* 49786470930SIngo Molnar * We dont want to block the signals - that would cause 49886470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 49986470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 50086470930SIngo Molnar * task, but being ignored by perf stat itself: 50186470930SIngo Molnar */ 502f7b7c26eSPeter Zijlstra atexit(sig_atexit); 50386470930SIngo Molnar signal(SIGINT, skip_signal); 50486470930SIngo Molnar signal(SIGALRM, skip_signal); 50586470930SIngo Molnar signal(SIGABRT, skip_signal); 50686470930SIngo Molnar 50742202dd5SIngo Molnar status = 0; 50842202dd5SIngo Molnar for (run_idx = 0; run_idx < run_count; run_idx++) { 50942202dd5SIngo Molnar if (run_count != 1 && verbose) 51042202dd5SIngo Molnar fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); 51142202dd5SIngo Molnar status = run_perf_stat(argc, argv); 51242202dd5SIngo Molnar } 51342202dd5SIngo Molnar 51442202dd5SIngo Molnar print_stat(argc, argv); 51542202dd5SIngo Molnar 51642202dd5SIngo Molnar return status; 51786470930SIngo Molnar } 518