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" 458f28827aSFrederic Weisbecker #include "util/event.h" 468f28827aSFrederic Weisbecker #include "util/debug.h" 4786470930SIngo Molnar 4886470930SIngo Molnar #include <sys/prctl.h> 4942202dd5SIngo Molnar #include <math.h> 5086470930SIngo Molnar 51cdd6c482SIngo Molnar static struct perf_event_attr default_attrs[] = { 5286470930SIngo Molnar 53f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 54f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES}, 55f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 56f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 5786470930SIngo Molnar 58f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 59f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 60f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES}, 61f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES }, 62f4dbfa8fSPeter Zijlstra 6386470930SIngo Molnar }; 6486470930SIngo Molnar 653d632595SJaswinder Singh Rajput static int system_wide = 0; 66f37a291cSIngo Molnar static unsigned int nr_cpus = 0; 6742202dd5SIngo Molnar static int run_idx = 0; 6842202dd5SIngo Molnar 693d632595SJaswinder Singh Rajput static int run_count = 1; 703d632595SJaswinder Singh Rajput static int inherit = 1; 713d632595SJaswinder Singh Rajput static int scale = 1; 72933da83aSChris Wilson static pid_t target_pid = -1; 73933da83aSChris Wilson static pid_t child_pid = -1; 740cfb7a13SIngo Molnar static int null_run = 0; 7542202dd5SIngo Molnar 763d632595SJaswinder Singh Rajput static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 7742202dd5SIngo Molnar 7863d40debSPeter Zijlstra static int event_scaled[MAX_COUNTERS]; 793d632595SJaswinder Singh Rajput 80506d4bc8SPeter Zijlstra struct stats 81506d4bc8SPeter Zijlstra { 828a02631aSPeter Zijlstra double n, mean, M2; 83506d4bc8SPeter Zijlstra }; 8442202dd5SIngo Molnar 859e9772c4SPeter Zijlstra static void update_stats(struct stats *stats, u64 val) 869e9772c4SPeter Zijlstra { 878a02631aSPeter Zijlstra double delta; 889e9772c4SPeter Zijlstra 898a02631aSPeter Zijlstra stats->n++; 908a02631aSPeter Zijlstra delta = val - stats->mean; 918a02631aSPeter Zijlstra stats->mean += delta / stats->n; 928a02631aSPeter Zijlstra stats->M2 += delta*(val - stats->mean); 939e9772c4SPeter Zijlstra } 949e9772c4SPeter Zijlstra 95506d4bc8SPeter Zijlstra static double avg_stats(struct stats *stats) 96506d4bc8SPeter Zijlstra { 978a02631aSPeter Zijlstra return stats->mean; 98506d4bc8SPeter Zijlstra } 9942202dd5SIngo Molnar 100506d4bc8SPeter Zijlstra /* 10163d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance 10263d40debSPeter Zijlstra * 10363d40debSPeter Zijlstra * (\Sum n_i^2) - ((\Sum n_i)^2)/n 1048a02631aSPeter Zijlstra * s^2 = ------------------------------- 10563d40debSPeter Zijlstra * n - 1 10663d40debSPeter Zijlstra * 10763d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Stddev 10863d40debSPeter Zijlstra * 10963d40debSPeter Zijlstra * The std dev of the mean is related to the std dev by: 11063d40debSPeter Zijlstra * 11163d40debSPeter Zijlstra * s 11263d40debSPeter Zijlstra * s_mean = ------- 11363d40debSPeter Zijlstra * sqrt(n) 11463d40debSPeter Zijlstra * 115506d4bc8SPeter Zijlstra */ 116506d4bc8SPeter Zijlstra static double stddev_stats(struct stats *stats) 117506d4bc8SPeter Zijlstra { 1188a02631aSPeter Zijlstra double variance = stats->M2 / (stats->n - 1); 1198a02631aSPeter Zijlstra double variance_mean = variance / stats->n; 12042202dd5SIngo Molnar 12163d40debSPeter Zijlstra return sqrt(variance_mean); 122506d4bc8SPeter Zijlstra } 12342202dd5SIngo Molnar 124506d4bc8SPeter Zijlstra struct stats event_res_stats[MAX_COUNTERS][3]; 125506d4bc8SPeter Zijlstra struct stats runtime_nsecs_stats; 126506d4bc8SPeter Zijlstra struct stats walltime_nsecs_stats; 127506d4bc8SPeter Zijlstra struct stats runtime_cycles_stats; 12811018201SAnton Blanchard struct stats runtime_branches_stats; 12986470930SIngo Molnar 130b9ebdcc0SJaswinder Singh Rajput #define MATCH_EVENT(t, c, counter) \ 131b9ebdcc0SJaswinder Singh Rajput (attrs[counter].type == PERF_TYPE_##t && \ 132b9ebdcc0SJaswinder Singh Rajput attrs[counter].config == PERF_COUNT_##c) 133b9ebdcc0SJaswinder Singh Rajput 134cca03c0aSJaswinder Singh Rajput #define ERR_PERF_OPEN \ 135cdd6c482SIngo Molnar "Error: counter %d, sys_perf_event_open() syscall returned with %d (%s)\n" 136cca03c0aSJaswinder Singh Rajput 137051ae7f7SPaul Mackerras static void create_perf_stat_counter(int counter, int pid) 13886470930SIngo Molnar { 139cdd6c482SIngo Molnar struct perf_event_attr *attr = attrs + counter; 14086470930SIngo Molnar 14186470930SIngo Molnar if (scale) 14286470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 14386470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 14486470930SIngo Molnar 14586470930SIngo Molnar if (system_wide) { 146f37a291cSIngo Molnar unsigned int cpu; 147f37a291cSIngo Molnar 14886470930SIngo Molnar for (cpu = 0; cpu < nr_cpus; cpu++) { 149cdd6c482SIngo Molnar fd[cpu][counter] = sys_perf_event_open(attr, -1, cpu, -1, 0); 150cca03c0aSJaswinder Singh Rajput if (fd[cpu][counter] < 0 && verbose) 151cca03c0aSJaswinder Singh Rajput fprintf(stderr, ERR_PERF_OPEN, counter, 152cca03c0aSJaswinder Singh Rajput fd[cpu][counter], strerror(errno)); 15386470930SIngo Molnar } 15486470930SIngo Molnar } else { 15586470930SIngo Molnar attr->inherit = inherit; 15686470930SIngo Molnar attr->disabled = 1; 15757e7986eSPaul Mackerras attr->enable_on_exec = 1; 15886470930SIngo Molnar 159cdd6c482SIngo Molnar fd[0][counter] = sys_perf_event_open(attr, pid, -1, -1, 0); 160cca03c0aSJaswinder Singh Rajput if (fd[0][counter] < 0 && verbose) 161cca03c0aSJaswinder Singh Rajput fprintf(stderr, ERR_PERF_OPEN, counter, 162cca03c0aSJaswinder Singh Rajput fd[0][counter], strerror(errno)); 16386470930SIngo Molnar } 16486470930SIngo Molnar } 16586470930SIngo Molnar 16686470930SIngo Molnar /* 16786470930SIngo Molnar * Does the counter have nsecs as a unit? 16886470930SIngo Molnar */ 16986470930SIngo Molnar static inline int nsec_counter(int counter) 17086470930SIngo Molnar { 171b9ebdcc0SJaswinder Singh Rajput if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) || 172b9ebdcc0SJaswinder Singh Rajput MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) 17386470930SIngo Molnar return 1; 17486470930SIngo Molnar 17586470930SIngo Molnar return 0; 17686470930SIngo Molnar } 17786470930SIngo Molnar 17886470930SIngo Molnar /* 17986470930SIngo Molnar * Read out the results of a single counter: 18086470930SIngo Molnar */ 18186470930SIngo Molnar static void read_counter(int counter) 18286470930SIngo Molnar { 183849abde9SPeter Zijlstra u64 count[3], single_count[3]; 184f37a291cSIngo Molnar unsigned int cpu; 185f37a291cSIngo Molnar size_t res, nv; 18686470930SIngo Molnar int scaled; 1879e9772c4SPeter Zijlstra int i; 18886470930SIngo Molnar 18986470930SIngo Molnar count[0] = count[1] = count[2] = 0; 19086470930SIngo Molnar 19186470930SIngo Molnar nv = scale ? 3 : 1; 19286470930SIngo Molnar for (cpu = 0; cpu < nr_cpus; cpu++) { 193743ee1f8SIngo Molnar if (fd[cpu][counter] < 0) 194743ee1f8SIngo Molnar continue; 195743ee1f8SIngo Molnar 1969cffa8d5SPaul Mackerras res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); 1979cffa8d5SPaul Mackerras assert(res == nv * sizeof(u64)); 198f37a291cSIngo Molnar 19942202dd5SIngo Molnar close(fd[cpu][counter]); 20042202dd5SIngo Molnar fd[cpu][counter] = -1; 20186470930SIngo Molnar 20286470930SIngo Molnar count[0] += single_count[0]; 20386470930SIngo Molnar if (scale) { 20486470930SIngo Molnar count[1] += single_count[1]; 20586470930SIngo Molnar count[2] += single_count[2]; 20686470930SIngo Molnar } 20786470930SIngo Molnar } 20886470930SIngo Molnar 20986470930SIngo Molnar scaled = 0; 21086470930SIngo Molnar if (scale) { 21186470930SIngo Molnar if (count[2] == 0) { 2129e9772c4SPeter Zijlstra event_scaled[counter] = -1; 21386470930SIngo Molnar count[0] = 0; 21486470930SIngo Molnar return; 21586470930SIngo Molnar } 21686470930SIngo Molnar 21786470930SIngo Molnar if (count[2] < count[1]) { 2189e9772c4SPeter Zijlstra event_scaled[counter] = 1; 21986470930SIngo Molnar count[0] = (unsigned long long) 22086470930SIngo Molnar ((double)count[0] * count[1] / count[2] + 0.5); 22186470930SIngo Molnar } 22286470930SIngo Molnar } 2239e9772c4SPeter Zijlstra 2249e9772c4SPeter Zijlstra for (i = 0; i < 3; i++) 2259e9772c4SPeter Zijlstra update_stats(&event_res_stats[counter][i], count[i]); 2269e9772c4SPeter Zijlstra 2279e9772c4SPeter Zijlstra if (verbose) { 2289e9772c4SPeter Zijlstra fprintf(stderr, "%s: %Ld %Ld %Ld\n", event_name(counter), 2299e9772c4SPeter Zijlstra count[0], count[1], count[2]); 2309e9772c4SPeter Zijlstra } 2319e9772c4SPeter Zijlstra 23286470930SIngo Molnar /* 23386470930SIngo Molnar * Save the full runtime - to allow normalization during printout: 23486470930SIngo Molnar */ 235b9ebdcc0SJaswinder Singh Rajput if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) 2369e9772c4SPeter Zijlstra update_stats(&runtime_nsecs_stats, count[0]); 237b9ebdcc0SJaswinder Singh Rajput if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter)) 2389e9772c4SPeter Zijlstra update_stats(&runtime_cycles_stats, count[0]); 23911018201SAnton Blanchard if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter)) 24011018201SAnton Blanchard update_stats(&runtime_branches_stats, count[0]); 24186470930SIngo Molnar } 24286470930SIngo Molnar 243f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv) 24486470930SIngo Molnar { 24586470930SIngo Molnar unsigned long long t0, t1; 24642202dd5SIngo Molnar int status = 0; 24786470930SIngo Molnar int counter; 24886470930SIngo Molnar int pid; 249051ae7f7SPaul Mackerras int child_ready_pipe[2], go_pipe[2]; 250051ae7f7SPaul Mackerras char buf; 25186470930SIngo Molnar 25286470930SIngo Molnar if (!system_wide) 25386470930SIngo Molnar nr_cpus = 1; 25486470930SIngo Molnar 255051ae7f7SPaul Mackerras if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) { 256051ae7f7SPaul Mackerras perror("failed to create pipes"); 257051ae7f7SPaul Mackerras exit(1); 258051ae7f7SPaul Mackerras } 259051ae7f7SPaul Mackerras 260051ae7f7SPaul Mackerras if ((pid = fork()) < 0) 261051ae7f7SPaul Mackerras perror("failed to fork"); 262051ae7f7SPaul Mackerras 263051ae7f7SPaul Mackerras if (!pid) { 264051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 265051ae7f7SPaul Mackerras close(go_pipe[1]); 266051ae7f7SPaul Mackerras fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 267051ae7f7SPaul Mackerras 268051ae7f7SPaul Mackerras /* 269051ae7f7SPaul Mackerras * Do a dummy execvp to get the PLT entry resolved, 270051ae7f7SPaul Mackerras * so we avoid the resolver overhead on the real 271051ae7f7SPaul Mackerras * execvp call. 272051ae7f7SPaul Mackerras */ 273051ae7f7SPaul Mackerras execvp("", (char **)argv); 274051ae7f7SPaul Mackerras 275051ae7f7SPaul Mackerras /* 276051ae7f7SPaul Mackerras * Tell the parent we're ready to go 277051ae7f7SPaul Mackerras */ 278051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 279051ae7f7SPaul Mackerras 280051ae7f7SPaul Mackerras /* 281051ae7f7SPaul Mackerras * Wait until the parent tells us to go. 282051ae7f7SPaul Mackerras */ 283a92bef0fSFrederic Weisbecker if (read(go_pipe[0], &buf, 1) == -1) 284a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 285051ae7f7SPaul Mackerras 286051ae7f7SPaul Mackerras execvp(argv[0], (char **)argv); 287051ae7f7SPaul Mackerras 288051ae7f7SPaul Mackerras perror(argv[0]); 289051ae7f7SPaul Mackerras exit(-1); 290051ae7f7SPaul Mackerras } 291051ae7f7SPaul Mackerras 292933da83aSChris Wilson child_pid = pid; 293933da83aSChris Wilson 294051ae7f7SPaul Mackerras /* 295051ae7f7SPaul Mackerras * Wait for the child to be ready to exec. 296051ae7f7SPaul Mackerras */ 297051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 298051ae7f7SPaul Mackerras close(go_pipe[0]); 299a92bef0fSFrederic Weisbecker if (read(child_ready_pipe[0], &buf, 1) == -1) 300a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 301051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 302051ae7f7SPaul Mackerras 30386470930SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 304051ae7f7SPaul Mackerras create_perf_stat_counter(counter, pid); 30586470930SIngo Molnar 30686470930SIngo Molnar /* 30786470930SIngo Molnar * Enable counters and exec the command: 30886470930SIngo Molnar */ 30986470930SIngo Molnar t0 = rdclock(); 31086470930SIngo Molnar 311051ae7f7SPaul Mackerras close(go_pipe[1]); 31242202dd5SIngo Molnar wait(&status); 31386470930SIngo Molnar 31486470930SIngo Molnar t1 = rdclock(); 31586470930SIngo Molnar 3169e9772c4SPeter Zijlstra update_stats(&walltime_nsecs_stats, t1 - t0); 31742202dd5SIngo Molnar 31842202dd5SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 31942202dd5SIngo Molnar read_counter(counter); 32042202dd5SIngo Molnar 32142202dd5SIngo Molnar return WEXITSTATUS(status); 32242202dd5SIngo Molnar } 32342202dd5SIngo Molnar 324849abde9SPeter Zijlstra static void print_noise(int counter, double avg) 32542202dd5SIngo Molnar { 326849abde9SPeter Zijlstra if (run_count == 1) 327849abde9SPeter Zijlstra return; 328849abde9SPeter Zijlstra 329849abde9SPeter Zijlstra fprintf(stderr, " ( +- %7.3f%% )", 330849abde9SPeter Zijlstra 100 * stddev_stats(&event_res_stats[counter][0]) / avg); 33142202dd5SIngo Molnar } 33242202dd5SIngo Molnar 333849abde9SPeter Zijlstra static void nsec_printout(int counter, double avg) 33442202dd5SIngo Molnar { 335506d4bc8SPeter Zijlstra double msecs = avg / 1e6; 33642202dd5SIngo Molnar 3376e750a8fSJaswinder Singh Rajput fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); 33842202dd5SIngo Molnar 339b9ebdcc0SJaswinder Singh Rajput if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { 34042202dd5SIngo Molnar fprintf(stderr, " # %10.3f CPUs ", 341506d4bc8SPeter Zijlstra avg / avg_stats(&walltime_nsecs_stats)); 34242202dd5SIngo Molnar } 34342202dd5SIngo Molnar } 34442202dd5SIngo Molnar 345849abde9SPeter Zijlstra static void abs_printout(int counter, double avg) 34642202dd5SIngo Molnar { 347c7f7fea3SIngo Molnar double total, ratio = 0.0; 348c7f7fea3SIngo Molnar 349506d4bc8SPeter Zijlstra fprintf(stderr, " %14.0f %-24s", avg, event_name(counter)); 35042202dd5SIngo Molnar 351506d4bc8SPeter Zijlstra if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { 352c7f7fea3SIngo Molnar total = avg_stats(&runtime_cycles_stats); 353c7f7fea3SIngo Molnar 354c7f7fea3SIngo Molnar if (total) 355c7f7fea3SIngo Molnar ratio = avg / total; 356c7f7fea3SIngo Molnar 357c7f7fea3SIngo Molnar fprintf(stderr, " # %10.3f IPC ", ratio); 35811018201SAnton Blanchard } else if (MATCH_EVENT(HARDWARE, HW_BRANCH_MISSES, counter)) { 35911018201SAnton Blanchard total = avg_stats(&runtime_branches_stats); 36011018201SAnton Blanchard 36111018201SAnton Blanchard if (total) 36211018201SAnton Blanchard ratio = avg * 100 / total; 36311018201SAnton Blanchard 36411018201SAnton Blanchard fprintf(stderr, " # %10.3f %% ", ratio); 36511018201SAnton Blanchard 36642202dd5SIngo Molnar } else { 367c7f7fea3SIngo Molnar total = avg_stats(&runtime_nsecs_stats); 368c7f7fea3SIngo Molnar 369c7f7fea3SIngo Molnar if (total) 370c7f7fea3SIngo Molnar ratio = 1000.0 * avg / total; 371c7f7fea3SIngo Molnar 372c7f7fea3SIngo Molnar fprintf(stderr, " # %10.3f M/sec", ratio); 37342202dd5SIngo Molnar } 37442202dd5SIngo Molnar } 37542202dd5SIngo Molnar 37642202dd5SIngo Molnar /* 37742202dd5SIngo Molnar * Print out the results of a single counter: 37842202dd5SIngo Molnar */ 37942202dd5SIngo Molnar static void print_counter(int counter) 38042202dd5SIngo Molnar { 381849abde9SPeter Zijlstra double avg = avg_stats(&event_res_stats[counter][0]); 38263d40debSPeter Zijlstra int scaled = event_scaled[counter]; 38342202dd5SIngo Molnar 38442202dd5SIngo Molnar if (scaled == -1) { 3856e750a8fSJaswinder Singh Rajput fprintf(stderr, " %14s %-24s\n", 38642202dd5SIngo Molnar "<not counted>", event_name(counter)); 38742202dd5SIngo Molnar return; 38842202dd5SIngo Molnar } 38942202dd5SIngo Molnar 39042202dd5SIngo Molnar if (nsec_counter(counter)) 391849abde9SPeter Zijlstra nsec_printout(counter, avg); 39242202dd5SIngo Molnar else 393849abde9SPeter Zijlstra abs_printout(counter, avg); 394849abde9SPeter Zijlstra 395849abde9SPeter Zijlstra print_noise(counter, avg); 39642202dd5SIngo Molnar 397506d4bc8SPeter Zijlstra if (scaled) { 398506d4bc8SPeter Zijlstra double avg_enabled, avg_running; 399506d4bc8SPeter Zijlstra 400506d4bc8SPeter Zijlstra avg_enabled = avg_stats(&event_res_stats[counter][1]); 401506d4bc8SPeter Zijlstra avg_running = avg_stats(&event_res_stats[counter][2]); 402506d4bc8SPeter Zijlstra 403210ad39fSIngo Molnar fprintf(stderr, " (scaled from %.2f%%)", 404506d4bc8SPeter Zijlstra 100 * avg_running / avg_enabled); 405506d4bc8SPeter Zijlstra } 40642202dd5SIngo Molnar 40742202dd5SIngo Molnar fprintf(stderr, "\n"); 40842202dd5SIngo Molnar } 40942202dd5SIngo Molnar 41042202dd5SIngo Molnar static void print_stat(int argc, const char **argv) 41142202dd5SIngo Molnar { 41242202dd5SIngo Molnar int i, counter; 41342202dd5SIngo Molnar 41486470930SIngo Molnar fflush(stdout); 41586470930SIngo Molnar 41686470930SIngo Molnar fprintf(stderr, "\n"); 41786470930SIngo Molnar fprintf(stderr, " Performance counter stats for \'%s", argv[0]); 41886470930SIngo Molnar 41986470930SIngo Molnar for (i = 1; i < argc; i++) 42086470930SIngo Molnar fprintf(stderr, " %s", argv[i]); 42186470930SIngo Molnar 42242202dd5SIngo Molnar fprintf(stderr, "\'"); 42342202dd5SIngo Molnar if (run_count > 1) 42442202dd5SIngo Molnar fprintf(stderr, " (%d runs)", run_count); 42542202dd5SIngo Molnar fprintf(stderr, ":\n\n"); 42686470930SIngo Molnar 42786470930SIngo Molnar for (counter = 0; counter < nr_counters; counter++) 42886470930SIngo Molnar print_counter(counter); 42986470930SIngo Molnar 43086470930SIngo Molnar fprintf(stderr, "\n"); 431566747e6SIngo Molnar fprintf(stderr, " %14.9f seconds time elapsed", 432506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)/1e9); 433566747e6SIngo Molnar if (run_count > 1) { 434566747e6SIngo Molnar fprintf(stderr, " ( +- %7.3f%% )", 435506d4bc8SPeter Zijlstra 100*stddev_stats(&walltime_nsecs_stats) / 436506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)); 437566747e6SIngo Molnar } 438566747e6SIngo Molnar fprintf(stderr, "\n\n"); 43986470930SIngo Molnar } 44086470930SIngo Molnar 441f7b7c26eSPeter Zijlstra static volatile int signr = -1; 442f7b7c26eSPeter Zijlstra 44386470930SIngo Molnar static void skip_signal(int signo) 44486470930SIngo Molnar { 445f7b7c26eSPeter Zijlstra signr = signo; 446f7b7c26eSPeter Zijlstra } 447f7b7c26eSPeter Zijlstra 448f7b7c26eSPeter Zijlstra static void sig_atexit(void) 449f7b7c26eSPeter Zijlstra { 450933da83aSChris Wilson if (child_pid != -1) 451933da83aSChris Wilson kill(child_pid, SIGTERM); 452933da83aSChris Wilson 453f7b7c26eSPeter Zijlstra if (signr == -1) 454f7b7c26eSPeter Zijlstra return; 455f7b7c26eSPeter Zijlstra 456f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 457f7b7c26eSPeter Zijlstra kill(getpid(), signr); 45886470930SIngo Molnar } 45986470930SIngo Molnar 46086470930SIngo Molnar static const char * const stat_usage[] = { 46186470930SIngo Molnar "perf stat [<options>] <command>", 46286470930SIngo Molnar NULL 46386470930SIngo Molnar }; 46486470930SIngo Molnar 46586470930SIngo Molnar static const struct option options[] = { 46686470930SIngo Molnar OPT_CALLBACK('e', "event", NULL, "event", 46786470930SIngo Molnar "event selector. use 'perf list' to list available events", 46886470930SIngo Molnar parse_events), 46986470930SIngo Molnar OPT_BOOLEAN('i', "inherit", &inherit, 47086470930SIngo Molnar "child tasks inherit counters"), 47186470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 47286470930SIngo Molnar "stat events on existing pid"), 47386470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 47486470930SIngo Molnar "system-wide collection from all CPUs"), 475b26bc5a7SBrice Goglin OPT_BOOLEAN('c', "scale", &scale, 47686470930SIngo Molnar "scale/normalize counters"), 477743ee1f8SIngo Molnar OPT_BOOLEAN('v', "verbose", &verbose, 478743ee1f8SIngo Molnar "be more verbose (show counter open errors, etc)"), 47942202dd5SIngo Molnar OPT_INTEGER('r', "repeat", &run_count, 48042202dd5SIngo Molnar "repeat command and print average + stddev (max: 100)"), 4810cfb7a13SIngo Molnar OPT_BOOLEAN('n', "null", &null_run, 4820cfb7a13SIngo Molnar "null run - dont start any counters"), 48386470930SIngo Molnar OPT_END() 48486470930SIngo Molnar }; 48586470930SIngo Molnar 486f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used) 48786470930SIngo Molnar { 48842202dd5SIngo Molnar int status; 48942202dd5SIngo Molnar 490a0541234SAnton Blanchard argc = parse_options(argc, argv, options, stat_usage, 491a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 49286470930SIngo Molnar if (!argc) 49386470930SIngo Molnar usage_with_options(stat_usage, options); 4949e9772c4SPeter Zijlstra if (run_count <= 0) 49542202dd5SIngo Molnar usage_with_options(stat_usage, options); 49686470930SIngo Molnar 497c3043569SJaswinder Singh Rajput /* Set attrs and nr_counters if no event is selected and !null_run */ 498c3043569SJaswinder Singh Rajput if (!null_run && !nr_counters) { 499c3043569SJaswinder Singh Rajput memcpy(attrs, default_attrs, sizeof(default_attrs)); 500c3043569SJaswinder Singh Rajput nr_counters = ARRAY_SIZE(default_attrs); 501c3043569SJaswinder Singh Rajput } 50286470930SIngo Molnar 50386470930SIngo Molnar nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 50486470930SIngo Molnar assert(nr_cpus <= MAX_NR_CPUS); 505f37a291cSIngo Molnar assert((int)nr_cpus >= 0); 50686470930SIngo Molnar 50786470930SIngo Molnar /* 50886470930SIngo Molnar * We dont want to block the signals - that would cause 50986470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 51086470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 51186470930SIngo Molnar * task, but being ignored by perf stat itself: 51286470930SIngo Molnar */ 513f7b7c26eSPeter Zijlstra atexit(sig_atexit); 51486470930SIngo Molnar signal(SIGINT, skip_signal); 51586470930SIngo Molnar signal(SIGALRM, skip_signal); 51686470930SIngo Molnar signal(SIGABRT, skip_signal); 51786470930SIngo Molnar 51842202dd5SIngo Molnar status = 0; 51942202dd5SIngo Molnar for (run_idx = 0; run_idx < run_count; run_idx++) { 52042202dd5SIngo Molnar if (run_count != 1 && verbose) 52142202dd5SIngo Molnar fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); 52242202dd5SIngo Molnar status = run_perf_stat(argc, argv); 52342202dd5SIngo Molnar } 52442202dd5SIngo Molnar 52542202dd5SIngo Molnar print_stat(argc, argv); 52642202dd5SIngo Molnar 52742202dd5SIngo Molnar return status; 52886470930SIngo Molnar } 529