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" 46361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 4769aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 488f28827aSFrederic Weisbecker #include "util/debug.h" 49a5d243d0SIngo Molnar #include "util/color.h" 5060666c63SLiming Wang #include "util/header.h" 51a12b51c4SPaul Mackerras #include "util/cpumap.h" 52d6d901c2SZhang, Yanmin #include "util/thread.h" 53fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 5486470930SIngo Molnar 5586470930SIngo Molnar #include <sys/prctl.h> 5642202dd5SIngo Molnar #include <math.h> 575af52b51SStephane Eranian #include <locale.h> 5886470930SIngo Molnar 59d7470b6aSStephane Eranian #define DEFAULT_SEPARATOR " " 60d7470b6aSStephane Eranian 61cdd6c482SIngo Molnar static struct perf_event_attr default_attrs[] = { 6286470930SIngo Molnar 63f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 64f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES }, 65f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 66f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 6786470930SIngo Molnar 68f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 69129c04cbSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 70129c04cbSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 71f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 7212133affSTim Blechmann { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 7312133affSTim Blechmann { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES }, 74f4dbfa8fSPeter Zijlstra 7586470930SIngo Molnar }; 7686470930SIngo Molnar 77c6264defSIngo Molnar /* 78c6264defSIngo Molnar * Detailed stats: 79c6264defSIngo Molnar */ 80c6264defSIngo Molnar static struct perf_event_attr detailed_attrs[] = { 81c6264defSIngo Molnar 82c6264defSIngo Molnar { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 83c6264defSIngo Molnar { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES }, 84c6264defSIngo Molnar { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 85c6264defSIngo Molnar { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 86c6264defSIngo Molnar 87c6264defSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 88129c04cbSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 89129c04cbSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 90c6264defSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 91c6264defSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 92c6264defSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES }, 93c6264defSIngo Molnar 94c6264defSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 95c6264defSIngo Molnar .config = 96c6264defSIngo Molnar PERF_COUNT_HW_CACHE_L1D << 0 | 97c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 98c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 99c6264defSIngo Molnar 100c6264defSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 101c6264defSIngo Molnar .config = 102c6264defSIngo Molnar PERF_COUNT_HW_CACHE_L1D << 0 | 103c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 104c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 105c6264defSIngo Molnar 106c6264defSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 107c6264defSIngo Molnar .config = 108c6264defSIngo Molnar PERF_COUNT_HW_CACHE_LL << 0 | 109c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 110c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 111c6264defSIngo Molnar 112c6264defSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 113c6264defSIngo Molnar .config = 114c6264defSIngo Molnar PERF_COUNT_HW_CACHE_LL << 0 | 115c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 116c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 117c6264defSIngo Molnar }; 118c6264defSIngo Molnar 119361c99a6SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 120361c99a6SArnaldo Carvalho de Melo 121c0555642SIan Munsie static bool system_wide = false; 12242202dd5SIngo Molnar static int run_idx = 0; 12342202dd5SIngo Molnar 1243d632595SJaswinder Singh Rajput static int run_count = 1; 1252e6cdf99SStephane Eranian static bool no_inherit = false; 126c0555642SIan Munsie static bool scale = true; 127f5b4a9c3SStephane Eranian static bool no_aggr = false; 128933da83aSChris Wilson static pid_t target_pid = -1; 129d6d901c2SZhang, Yanmin static pid_t target_tid = -1; 130933da83aSChris Wilson static pid_t child_pid = -1; 131c0555642SIan Munsie static bool null_run = false; 132c6264defSIngo Molnar static bool detailed_run = false; 133f9cef0a9SIngo Molnar static bool sync_run = false; 134201e0b06SArnaldo Carvalho de Melo static bool big_num = true; 135d7470b6aSStephane Eranian static int big_num_opt = -1; 136c45c6ea2SStephane Eranian static const char *cpu_list; 137d7470b6aSStephane Eranian static const char *csv_sep = NULL; 138d7470b6aSStephane Eranian static bool csv_output = false; 1395af52b51SStephane Eranian 14060666c63SLiming Wang static volatile int done = 0; 14160666c63SLiming Wang 142506d4bc8SPeter Zijlstra struct stats 143506d4bc8SPeter Zijlstra { 1448a02631aSPeter Zijlstra double n, mean, M2; 145506d4bc8SPeter Zijlstra }; 14642202dd5SIngo Molnar 14769aad6f1SArnaldo Carvalho de Melo struct perf_stat { 14869aad6f1SArnaldo Carvalho de Melo struct stats res_stats[3]; 14969aad6f1SArnaldo Carvalho de Melo }; 15069aad6f1SArnaldo Carvalho de Melo 151c52b12edSArnaldo Carvalho de Melo static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 15269aad6f1SArnaldo Carvalho de Melo { 153c52b12edSArnaldo Carvalho de Melo evsel->priv = zalloc(sizeof(struct perf_stat)); 15469aad6f1SArnaldo Carvalho de Melo return evsel->priv == NULL ? -ENOMEM : 0; 15569aad6f1SArnaldo Carvalho de Melo } 15669aad6f1SArnaldo Carvalho de Melo 15769aad6f1SArnaldo Carvalho de Melo static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 15869aad6f1SArnaldo Carvalho de Melo { 15969aad6f1SArnaldo Carvalho de Melo free(evsel->priv); 16069aad6f1SArnaldo Carvalho de Melo evsel->priv = NULL; 16169aad6f1SArnaldo Carvalho de Melo } 16269aad6f1SArnaldo Carvalho de Melo 1639e9772c4SPeter Zijlstra static void update_stats(struct stats *stats, u64 val) 1649e9772c4SPeter Zijlstra { 1658a02631aSPeter Zijlstra double delta; 1669e9772c4SPeter Zijlstra 1678a02631aSPeter Zijlstra stats->n++; 1688a02631aSPeter Zijlstra delta = val - stats->mean; 1698a02631aSPeter Zijlstra stats->mean += delta / stats->n; 1708a02631aSPeter Zijlstra stats->M2 += delta*(val - stats->mean); 1719e9772c4SPeter Zijlstra } 1729e9772c4SPeter Zijlstra 173506d4bc8SPeter Zijlstra static double avg_stats(struct stats *stats) 174506d4bc8SPeter Zijlstra { 1758a02631aSPeter Zijlstra return stats->mean; 176506d4bc8SPeter Zijlstra } 17742202dd5SIngo Molnar 178506d4bc8SPeter Zijlstra /* 17963d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance 18063d40debSPeter Zijlstra * 18163d40debSPeter Zijlstra * (\Sum n_i^2) - ((\Sum n_i)^2)/n 1828a02631aSPeter Zijlstra * s^2 = ------------------------------- 18363d40debSPeter Zijlstra * n - 1 18463d40debSPeter Zijlstra * 18563d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Stddev 18663d40debSPeter Zijlstra * 18763d40debSPeter Zijlstra * The std dev of the mean is related to the std dev by: 18863d40debSPeter Zijlstra * 18963d40debSPeter Zijlstra * s 19063d40debSPeter Zijlstra * s_mean = ------- 19163d40debSPeter Zijlstra * sqrt(n) 19263d40debSPeter Zijlstra * 193506d4bc8SPeter Zijlstra */ 194506d4bc8SPeter Zijlstra static double stddev_stats(struct stats *stats) 195506d4bc8SPeter Zijlstra { 1968a02631aSPeter Zijlstra double variance = stats->M2 / (stats->n - 1); 1978a02631aSPeter Zijlstra double variance_mean = variance / stats->n; 19842202dd5SIngo Molnar 19963d40debSPeter Zijlstra return sqrt(variance_mean); 200506d4bc8SPeter Zijlstra } 20142202dd5SIngo Molnar 202f5b4a9c3SStephane Eranian struct stats runtime_nsecs_stats[MAX_NR_CPUS]; 203f5b4a9c3SStephane Eranian struct stats runtime_cycles_stats[MAX_NR_CPUS]; 204d3d1e86dSIngo Molnar struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS]; 205d3d1e86dSIngo Molnar struct stats runtime_stalled_cycles_back_stats[MAX_NR_CPUS]; 206f5b4a9c3SStephane Eranian struct stats runtime_branches_stats[MAX_NR_CPUS]; 207d58f4c82SIngo Molnar struct stats runtime_cacherefs_stats[MAX_NR_CPUS]; 2088bb6c79fSIngo Molnar struct stats runtime_l1_dcache_stats[MAX_NR_CPUS]; 209506d4bc8SPeter Zijlstra struct stats walltime_nsecs_stats; 21086470930SIngo Molnar 21148290609SArnaldo Carvalho de Melo static int create_perf_stat_counter(struct perf_evsel *evsel) 21286470930SIngo Molnar { 21369aad6f1SArnaldo Carvalho de Melo struct perf_event_attr *attr = &evsel->attr; 21486470930SIngo Molnar 21586470930SIngo Molnar if (scale) 21686470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 21786470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 21886470930SIngo Molnar 2192e6cdf99SStephane Eranian attr->inherit = !no_inherit; 2205d2cd909SArnaldo Carvalho de Melo 2215d2cd909SArnaldo Carvalho de Melo if (system_wide) 2225d2cd909SArnaldo Carvalho de Melo return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false); 2235d2cd909SArnaldo Carvalho de Melo 2242e6cdf99SStephane Eranian if (target_pid == -1 && target_tid == -1) { 22586470930SIngo Molnar attr->disabled = 1; 22657e7986eSPaul Mackerras attr->enable_on_exec = 1; 2276be2850eSZhang, Yanmin } 228084ab9f8SArnaldo Carvalho de Melo 2295d2cd909SArnaldo Carvalho de Melo return perf_evsel__open_per_thread(evsel, evsel_list->threads, false); 23086470930SIngo Molnar } 23186470930SIngo Molnar 23286470930SIngo Molnar /* 23386470930SIngo Molnar * Does the counter have nsecs as a unit? 23486470930SIngo Molnar */ 235daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel) 23686470930SIngo Molnar { 237daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) || 238daec78a0SArnaldo Carvalho de Melo perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 23986470930SIngo Molnar return 1; 24086470930SIngo Molnar 24186470930SIngo Molnar return 0; 24286470930SIngo Molnar } 24386470930SIngo Molnar 24486470930SIngo Molnar /* 245dcd9936aSIngo Molnar * Update various tracking values we maintain to print 246dcd9936aSIngo Molnar * more semantic information such as miss/hit ratios, 247dcd9936aSIngo Molnar * instruction rates, etc: 248dcd9936aSIngo Molnar */ 249dcd9936aSIngo Molnar static void update_shadow_stats(struct perf_evsel *counter, u64 *count) 250dcd9936aSIngo Molnar { 251dcd9936aSIngo Molnar if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 252dcd9936aSIngo Molnar update_stats(&runtime_nsecs_stats[0], count[0]); 253dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 254dcd9936aSIngo Molnar update_stats(&runtime_cycles_stats[0], count[0]); 255d3d1e86dSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 256d3d1e86dSIngo Molnar update_stats(&runtime_stalled_cycles_front_stats[0], count[0]); 257129c04cbSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 258d3d1e86dSIngo Molnar update_stats(&runtime_stalled_cycles_back_stats[0], count[0]); 259dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 260dcd9936aSIngo Molnar update_stats(&runtime_branches_stats[0], count[0]); 261dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 262dcd9936aSIngo Molnar update_stats(&runtime_cacherefs_stats[0], count[0]); 2638bb6c79fSIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) 2648bb6c79fSIngo Molnar update_stats(&runtime_l1_dcache_stats[0], count[0]); 265dcd9936aSIngo Molnar } 266dcd9936aSIngo Molnar 267dcd9936aSIngo Molnar /* 26886470930SIngo Molnar * Read out the results of a single counter: 269f5b4a9c3SStephane Eranian * aggregate counts across CPUs in system-wide mode 27086470930SIngo Molnar */ 271c52b12edSArnaldo Carvalho de Melo static int read_counter_aggr(struct perf_evsel *counter) 27286470930SIngo Molnar { 27369aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps = counter->priv; 274c52b12edSArnaldo Carvalho de Melo u64 *count = counter->counts->aggr.values; 275c52b12edSArnaldo Carvalho de Melo int i; 27686470930SIngo Molnar 2777e2ed097SArnaldo Carvalho de Melo if (__perf_evsel__read(counter, evsel_list->cpus->nr, 2787e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr, scale) < 0) 279c52b12edSArnaldo Carvalho de Melo return -1; 2809e9772c4SPeter Zijlstra 2819e9772c4SPeter Zijlstra for (i = 0; i < 3; i++) 28269aad6f1SArnaldo Carvalho de Melo update_stats(&ps->res_stats[i], count[i]); 2839e9772c4SPeter Zijlstra 2849e9772c4SPeter Zijlstra if (verbose) { 2859486aa38SArnaldo Carvalho de Melo fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 2869486aa38SArnaldo Carvalho de Melo event_name(counter), count[0], count[1], count[2]); 2879e9772c4SPeter Zijlstra } 2889e9772c4SPeter Zijlstra 28986470930SIngo Molnar /* 29086470930SIngo Molnar * Save the full runtime - to allow normalization during printout: 29186470930SIngo Molnar */ 292dcd9936aSIngo Molnar update_shadow_stats(counter, count); 293c52b12edSArnaldo Carvalho de Melo 294c52b12edSArnaldo Carvalho de Melo return 0; 295f5b4a9c3SStephane Eranian } 296f5b4a9c3SStephane Eranian 297f5b4a9c3SStephane Eranian /* 298f5b4a9c3SStephane Eranian * Read out the results of a single counter: 299f5b4a9c3SStephane Eranian * do not aggregate counts across CPUs in system-wide mode 300f5b4a9c3SStephane Eranian */ 301c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter) 302f5b4a9c3SStephane Eranian { 303c52b12edSArnaldo Carvalho de Melo u64 *count; 304f5b4a9c3SStephane Eranian int cpu; 305f5b4a9c3SStephane Eranian 3067e2ed097SArnaldo Carvalho de Melo for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 307c52b12edSArnaldo Carvalho de Melo if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 308c52b12edSArnaldo Carvalho de Melo return -1; 309f5b4a9c3SStephane Eranian 310c52b12edSArnaldo Carvalho de Melo count = counter->counts->cpu[cpu].values; 311f5b4a9c3SStephane Eranian 312dcd9936aSIngo Molnar update_shadow_stats(counter, count); 313f5b4a9c3SStephane Eranian } 314c52b12edSArnaldo Carvalho de Melo 315c52b12edSArnaldo Carvalho de Melo return 0; 31686470930SIngo Molnar } 31786470930SIngo Molnar 318f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv) 31986470930SIngo Molnar { 32086470930SIngo Molnar unsigned long long t0, t1; 32169aad6f1SArnaldo Carvalho de Melo struct perf_evsel *counter; 32242202dd5SIngo Molnar int status = 0; 323051ae7f7SPaul Mackerras int child_ready_pipe[2], go_pipe[2]; 3246be2850eSZhang, Yanmin const bool forks = (argc > 0); 325051ae7f7SPaul Mackerras char buf; 32686470930SIngo Molnar 32760666c63SLiming Wang if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 328051ae7f7SPaul Mackerras perror("failed to create pipes"); 329051ae7f7SPaul Mackerras exit(1); 330051ae7f7SPaul Mackerras } 331051ae7f7SPaul Mackerras 33260666c63SLiming Wang if (forks) { 3336be2850eSZhang, Yanmin if ((child_pid = fork()) < 0) 334051ae7f7SPaul Mackerras perror("failed to fork"); 335051ae7f7SPaul Mackerras 3366be2850eSZhang, Yanmin if (!child_pid) { 337051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 338051ae7f7SPaul Mackerras close(go_pipe[1]); 339051ae7f7SPaul Mackerras fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 340051ae7f7SPaul Mackerras 341051ae7f7SPaul Mackerras /* 342051ae7f7SPaul Mackerras * Do a dummy execvp to get the PLT entry resolved, 343051ae7f7SPaul Mackerras * so we avoid the resolver overhead on the real 344051ae7f7SPaul Mackerras * execvp call. 345051ae7f7SPaul Mackerras */ 346051ae7f7SPaul Mackerras execvp("", (char **)argv); 347051ae7f7SPaul Mackerras 348051ae7f7SPaul Mackerras /* 349051ae7f7SPaul Mackerras * Tell the parent we're ready to go 350051ae7f7SPaul Mackerras */ 351051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 352051ae7f7SPaul Mackerras 353051ae7f7SPaul Mackerras /* 354051ae7f7SPaul Mackerras * Wait until the parent tells us to go. 355051ae7f7SPaul Mackerras */ 356a92bef0fSFrederic Weisbecker if (read(go_pipe[0], &buf, 1) == -1) 357a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 358051ae7f7SPaul Mackerras 359051ae7f7SPaul Mackerras execvp(argv[0], (char **)argv); 360051ae7f7SPaul Mackerras 361051ae7f7SPaul Mackerras perror(argv[0]); 362051ae7f7SPaul Mackerras exit(-1); 363051ae7f7SPaul Mackerras } 364051ae7f7SPaul Mackerras 365d6d901c2SZhang, Yanmin if (target_tid == -1 && target_pid == -1 && !system_wide) 3667e2ed097SArnaldo Carvalho de Melo evsel_list->threads->map[0] = child_pid; 367d6d901c2SZhang, Yanmin 368051ae7f7SPaul Mackerras /* 369051ae7f7SPaul Mackerras * Wait for the child to be ready to exec. 370051ae7f7SPaul Mackerras */ 371051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 372051ae7f7SPaul Mackerras close(go_pipe[0]); 373a92bef0fSFrederic Weisbecker if (read(child_ready_pipe[0], &buf, 1) == -1) 374a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 375051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 37660666c63SLiming Wang } 377051ae7f7SPaul Mackerras 378361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 37948290609SArnaldo Carvalho de Melo if (create_perf_stat_counter(counter) < 0) { 380ede70290SIngo Molnar if (errno == EINVAL || errno == ENOSYS) 381ede70290SIngo Molnar continue; 382ede70290SIngo Molnar 383ede70290SIngo Molnar if (errno == EPERM || errno == EACCES) { 384d9cf837eSCorey Ashford error("You may not have permission to collect %sstats.\n" 385d9cf837eSCorey Ashford "\t Consider tweaking" 386d9cf837eSCorey Ashford " /proc/sys/kernel/perf_event_paranoid or running as root.", 387084ab9f8SArnaldo Carvalho de Melo system_wide ? "system-wide " : ""); 3885a3446bcSDavid Ahern } else if (errno == ENOENT) { 3895a3446bcSDavid Ahern error("%s event is not supported. ", event_name(counter)); 39048290609SArnaldo Carvalho de Melo } else { 39148290609SArnaldo Carvalho de Melo error("open_counter returned with %d (%s). " 39248290609SArnaldo Carvalho de Melo "/bin/dmesg may provide additional information.\n", 39348290609SArnaldo Carvalho de Melo errno, strerror(errno)); 39448290609SArnaldo Carvalho de Melo } 395084ab9f8SArnaldo Carvalho de Melo if (child_pid != -1) 396084ab9f8SArnaldo Carvalho de Melo kill(child_pid, SIGTERM); 39748290609SArnaldo Carvalho de Melo die("Not all events could be opened.\n"); 398084ab9f8SArnaldo Carvalho de Melo return -1; 399084ab9f8SArnaldo Carvalho de Melo } 40048290609SArnaldo Carvalho de Melo } 40186470930SIngo Molnar 402cfd748aeSFrederic Weisbecker if (perf_evlist__set_filters(evsel_list)) { 403cfd748aeSFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 404cfd748aeSFrederic Weisbecker strerror(errno)); 405cfd748aeSFrederic Weisbecker return -1; 406cfd748aeSFrederic Weisbecker } 407cfd748aeSFrederic Weisbecker 40886470930SIngo Molnar /* 40986470930SIngo Molnar * Enable counters and exec the command: 41086470930SIngo Molnar */ 41186470930SIngo Molnar t0 = rdclock(); 41286470930SIngo Molnar 41360666c63SLiming Wang if (forks) { 414051ae7f7SPaul Mackerras close(go_pipe[1]); 41542202dd5SIngo Molnar wait(&status); 41660666c63SLiming Wang } else { 4176be2850eSZhang, Yanmin while(!done) sleep(1); 41860666c63SLiming Wang } 41986470930SIngo Molnar 42086470930SIngo Molnar t1 = rdclock(); 42186470930SIngo Molnar 4229e9772c4SPeter Zijlstra update_stats(&walltime_nsecs_stats, t1 - t0); 42342202dd5SIngo Molnar 424f5b4a9c3SStephane Eranian if (no_aggr) { 425361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 42642202dd5SIngo Molnar read_counter(counter); 4277e2ed097SArnaldo Carvalho de Melo perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); 428f5b4a9c3SStephane Eranian } 429c52b12edSArnaldo Carvalho de Melo } else { 430361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 431c52b12edSArnaldo Carvalho de Melo read_counter_aggr(counter); 4327e2ed097SArnaldo Carvalho de Melo perf_evsel__close_fd(counter, evsel_list->cpus->nr, 4337e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr); 434c52b12edSArnaldo Carvalho de Melo } 435c52b12edSArnaldo Carvalho de Melo } 436c52b12edSArnaldo Carvalho de Melo 43742202dd5SIngo Molnar return WEXITSTATUS(status); 43842202dd5SIngo Molnar } 43942202dd5SIngo Molnar 440f99844cbSIngo Molnar static void print_noise_pct(double total, double avg) 441f99844cbSIngo Molnar { 442f99844cbSIngo Molnar double pct = 0.0; 443f99844cbSIngo Molnar 444f99844cbSIngo Molnar if (avg) 445f99844cbSIngo Molnar pct = 100.0*total/avg; 446f99844cbSIngo Molnar 447f99844cbSIngo Molnar fprintf(stderr, " ( +-%6.2f%% )", pct); 448f99844cbSIngo Molnar } 449f99844cbSIngo Molnar 45069aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg) 45142202dd5SIngo Molnar { 45269aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps; 45369aad6f1SArnaldo Carvalho de Melo 454849abde9SPeter Zijlstra if (run_count == 1) 455849abde9SPeter Zijlstra return; 456849abde9SPeter Zijlstra 45769aad6f1SArnaldo Carvalho de Melo ps = evsel->priv; 458f99844cbSIngo Molnar print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 45942202dd5SIngo Molnar } 46042202dd5SIngo Molnar 461daec78a0SArnaldo Carvalho de Melo static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) 46242202dd5SIngo Molnar { 463506d4bc8SPeter Zijlstra double msecs = avg / 1e6; 464d7470b6aSStephane Eranian char cpustr[16] = { '\0', }; 465d7470b6aSStephane Eranian const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s"; 46642202dd5SIngo Molnar 467f5b4a9c3SStephane Eranian if (no_aggr) 468d7470b6aSStephane Eranian sprintf(cpustr, "CPU%*d%s", 469d7470b6aSStephane Eranian csv_output ? 0 : -4, 4707e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep); 471d7470b6aSStephane Eranian 472daec78a0SArnaldo Carvalho de Melo fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 473d7470b6aSStephane Eranian 474023695d9SStephane Eranian if (evsel->cgrp) 475023695d9SStephane Eranian fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name); 476023695d9SStephane Eranian 477d7470b6aSStephane Eranian if (csv_output) 478d7470b6aSStephane Eranian return; 47942202dd5SIngo Molnar 480daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 481481f988aSIngo Molnar fprintf(stderr, " # %8.3f CPUs utilized ", avg / avg_stats(&walltime_nsecs_stats)); 48242202dd5SIngo Molnar } 48342202dd5SIngo Molnar 484d3d1e86dSIngo Molnar static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) 485d3d1e86dSIngo Molnar { 486d3d1e86dSIngo Molnar double total, ratio = 0.0; 487d3d1e86dSIngo Molnar const char *color; 488d3d1e86dSIngo Molnar 489d3d1e86dSIngo Molnar total = avg_stats(&runtime_cycles_stats[cpu]); 490d3d1e86dSIngo Molnar 491d3d1e86dSIngo Molnar if (total) 492d3d1e86dSIngo Molnar ratio = avg / total * 100.0; 493d3d1e86dSIngo Molnar 494d3d1e86dSIngo Molnar color = PERF_COLOR_NORMAL; 495d3d1e86dSIngo Molnar if (ratio > 75.0) 496d3d1e86dSIngo Molnar color = PERF_COLOR_RED; 497d3d1e86dSIngo Molnar else if (ratio > 50.0) 498d3d1e86dSIngo Molnar color = PERF_COLOR_MAGENTA; 499d3d1e86dSIngo Molnar else if (ratio > 20.0) 500d3d1e86dSIngo Molnar color = PERF_COLOR_YELLOW; 501d3d1e86dSIngo Molnar 502d3d1e86dSIngo Molnar fprintf(stderr, " # "); 503d3d1e86dSIngo Molnar color_fprintf(stderr, color, "%5.2f%%", ratio); 504d3d1e86dSIngo Molnar fprintf(stderr, " frontend cycles idle "); 505d3d1e86dSIngo Molnar } 506d3d1e86dSIngo Molnar 507d3d1e86dSIngo Molnar static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) 508a5d243d0SIngo Molnar { 509a5d243d0SIngo Molnar double total, ratio = 0.0; 510a5d243d0SIngo Molnar const char *color; 511a5d243d0SIngo Molnar 512a5d243d0SIngo Molnar total = avg_stats(&runtime_cycles_stats[cpu]); 513a5d243d0SIngo Molnar 514a5d243d0SIngo Molnar if (total) 515a5d243d0SIngo Molnar ratio = avg / total * 100.0; 516a5d243d0SIngo Molnar 517a5d243d0SIngo Molnar color = PERF_COLOR_NORMAL; 518a5d243d0SIngo Molnar if (ratio > 75.0) 519a5d243d0SIngo Molnar color = PERF_COLOR_RED; 520a5d243d0SIngo Molnar else if (ratio > 50.0) 521a5d243d0SIngo Molnar color = PERF_COLOR_MAGENTA; 522a5d243d0SIngo Molnar else if (ratio > 25.0) 523a5d243d0SIngo Molnar color = PERF_COLOR_YELLOW; 524a5d243d0SIngo Molnar 525a5d243d0SIngo Molnar fprintf(stderr, " # "); 526a5d243d0SIngo Molnar color_fprintf(stderr, color, "%5.2f%%", ratio); 527d3d1e86dSIngo Molnar fprintf(stderr, " backend cycles idle "); 528a5d243d0SIngo Molnar } 529a5d243d0SIngo Molnar 530c78df6c1SIngo Molnar static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) 531c78df6c1SIngo Molnar { 532c78df6c1SIngo Molnar double total, ratio = 0.0; 533c78df6c1SIngo Molnar const char *color; 534c78df6c1SIngo Molnar 535c78df6c1SIngo Molnar total = avg_stats(&runtime_branches_stats[cpu]); 536c78df6c1SIngo Molnar 537c78df6c1SIngo Molnar if (total) 538c78df6c1SIngo Molnar ratio = avg / total * 100.0; 539c78df6c1SIngo Molnar 540c78df6c1SIngo Molnar color = PERF_COLOR_NORMAL; 541c78df6c1SIngo Molnar if (ratio > 20.0) 542c78df6c1SIngo Molnar color = PERF_COLOR_RED; 543c78df6c1SIngo Molnar else if (ratio > 10.0) 544c78df6c1SIngo Molnar color = PERF_COLOR_MAGENTA; 545c78df6c1SIngo Molnar else if (ratio > 5.0) 546c78df6c1SIngo Molnar color = PERF_COLOR_YELLOW; 547c78df6c1SIngo Molnar 548c78df6c1SIngo Molnar fprintf(stderr, " # "); 549c78df6c1SIngo Molnar color_fprintf(stderr, color, "%5.2f%%", ratio); 550c78df6c1SIngo Molnar fprintf(stderr, " of all branches "); 551c78df6c1SIngo Molnar } 552c78df6c1SIngo Molnar 5538bb6c79fSIngo Molnar static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 5548bb6c79fSIngo Molnar { 5558bb6c79fSIngo Molnar double total, ratio = 0.0; 5568bb6c79fSIngo Molnar const char *color; 5578bb6c79fSIngo Molnar 5588bb6c79fSIngo Molnar total = avg_stats(&runtime_l1_dcache_stats[cpu]); 5598bb6c79fSIngo Molnar 5608bb6c79fSIngo Molnar if (total) 5618bb6c79fSIngo Molnar ratio = avg / total * 100.0; 5628bb6c79fSIngo Molnar 5638bb6c79fSIngo Molnar color = PERF_COLOR_NORMAL; 5648bb6c79fSIngo Molnar if (ratio > 20.0) 5658bb6c79fSIngo Molnar color = PERF_COLOR_RED; 5668bb6c79fSIngo Molnar else if (ratio > 10.0) 5678bb6c79fSIngo Molnar color = PERF_COLOR_MAGENTA; 5688bb6c79fSIngo Molnar else if (ratio > 5.0) 5698bb6c79fSIngo Molnar color = PERF_COLOR_YELLOW; 5708bb6c79fSIngo Molnar 5718bb6c79fSIngo Molnar fprintf(stderr, " # "); 5728bb6c79fSIngo Molnar color_fprintf(stderr, color, "%5.2f%%", ratio); 5738bb6c79fSIngo Molnar fprintf(stderr, " of all L1-dcache hits "); 5748bb6c79fSIngo Molnar } 5758bb6c79fSIngo Molnar 576daec78a0SArnaldo Carvalho de Melo static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) 57742202dd5SIngo Molnar { 578c7f7fea3SIngo Molnar double total, ratio = 0.0; 579f5b4a9c3SStephane Eranian char cpustr[16] = { '\0', }; 580d7470b6aSStephane Eranian const char *fmt; 581d7470b6aSStephane Eranian 582d7470b6aSStephane Eranian if (csv_output) 583d7470b6aSStephane Eranian fmt = "%s%.0f%s%s"; 584d7470b6aSStephane Eranian else if (big_num) 585d7470b6aSStephane Eranian fmt = "%s%'18.0f%s%-24s"; 586d7470b6aSStephane Eranian else 587d7470b6aSStephane Eranian fmt = "%s%18.0f%s%-24s"; 588f5b4a9c3SStephane Eranian 589f5b4a9c3SStephane Eranian if (no_aggr) 590d7470b6aSStephane Eranian sprintf(cpustr, "CPU%*d%s", 591d7470b6aSStephane Eranian csv_output ? 0 : -4, 5927e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep); 593f5b4a9c3SStephane Eranian else 594f5b4a9c3SStephane Eranian cpu = 0; 595c7f7fea3SIngo Molnar 596daec78a0SArnaldo Carvalho de Melo fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel)); 597d7470b6aSStephane Eranian 598023695d9SStephane Eranian if (evsel->cgrp) 599023695d9SStephane Eranian fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name); 600023695d9SStephane Eranian 601d7470b6aSStephane Eranian if (csv_output) 602d7470b6aSStephane Eranian return; 60342202dd5SIngo Molnar 604daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 605f5b4a9c3SStephane Eranian total = avg_stats(&runtime_cycles_stats[cpu]); 606c7f7fea3SIngo Molnar 607c7f7fea3SIngo Molnar if (total) 608c7f7fea3SIngo Molnar ratio = avg / total; 609c7f7fea3SIngo Molnar 610481f988aSIngo Molnar fprintf(stderr, " # %4.2f insns per cycle ", ratio); 611481f988aSIngo Molnar 612d3d1e86dSIngo Molnar total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 613d3d1e86dSIngo Molnar total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 614481f988aSIngo Molnar 615481f988aSIngo Molnar if (total && avg) { 616481f988aSIngo Molnar ratio = total / avg; 617481f988aSIngo Molnar fprintf(stderr, "\n # %4.2f stalled cycles per insn", ratio); 618481f988aSIngo Molnar } 619481f988aSIngo Molnar 620daec78a0SArnaldo Carvalho de Melo } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && 621f5b4a9c3SStephane Eranian runtime_branches_stats[cpu].n != 0) { 622c78df6c1SIngo Molnar print_branch_misses(cpu, evsel, avg); 6238bb6c79fSIngo Molnar } else if ( 6248bb6c79fSIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 6258bb6c79fSIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | 6268bb6c79fSIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 6278bb6c79fSIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 628c6264defSIngo Molnar runtime_l1_dcache_stats[cpu].n != 0) { 6298bb6c79fSIngo Molnar print_l1_dcache_misses(cpu, evsel, avg); 630d58f4c82SIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) && 631d58f4c82SIngo Molnar runtime_cacherefs_stats[cpu].n != 0) { 632d58f4c82SIngo Molnar total = avg_stats(&runtime_cacherefs_stats[cpu]); 633d58f4c82SIngo Molnar 634d58f4c82SIngo Molnar if (total) 635d58f4c82SIngo Molnar ratio = avg * 100 / total; 636d58f4c82SIngo Molnar 637481f988aSIngo Molnar fprintf(stderr, " # %8.3f %% of all cache refs ", ratio); 638d58f4c82SIngo Molnar 639d3d1e86dSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { 640d3d1e86dSIngo Molnar print_stalled_cycles_frontend(cpu, evsel, avg); 641129c04cbSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) { 642d3d1e86dSIngo Molnar print_stalled_cycles_backend(cpu, evsel, avg); 643481f988aSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 644481f988aSIngo Molnar total = avg_stats(&runtime_nsecs_stats[cpu]); 645481f988aSIngo Molnar 646481f988aSIngo Molnar if (total) 647481f988aSIngo Molnar ratio = 1.0 * avg / total; 648481f988aSIngo Molnar 649481f988aSIngo Molnar fprintf(stderr, " # %8.3f GHz ", ratio); 650481f988aSIngo Molnar } else if (runtime_nsecs_stats[cpu].n != 0) { 651481f988aSIngo Molnar total = avg_stats(&runtime_nsecs_stats[cpu]); 652481f988aSIngo Molnar 653481f988aSIngo Molnar if (total) 654481f988aSIngo Molnar ratio = 1000.0 * avg / total; 655481f988aSIngo Molnar 656481f988aSIngo Molnar fprintf(stderr, " # %8.3f M/sec ", ratio); 657a5d243d0SIngo Molnar } else { 658a5d243d0SIngo Molnar fprintf(stderr, " "); 65942202dd5SIngo Molnar } 66042202dd5SIngo Molnar } 66142202dd5SIngo Molnar 66242202dd5SIngo Molnar /* 66342202dd5SIngo Molnar * Print out the results of a single counter: 664f5b4a9c3SStephane Eranian * aggregated counts in system-wide mode 66542202dd5SIngo Molnar */ 66669aad6f1SArnaldo Carvalho de Melo static void print_counter_aggr(struct perf_evsel *counter) 66742202dd5SIngo Molnar { 66869aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps = counter->priv; 66969aad6f1SArnaldo Carvalho de Melo double avg = avg_stats(&ps->res_stats[0]); 670c52b12edSArnaldo Carvalho de Melo int scaled = counter->counts->scaled; 67142202dd5SIngo Molnar 67242202dd5SIngo Molnar if (scaled == -1) { 673023695d9SStephane Eranian fprintf(stderr, "%*s%s%*s", 674d7470b6aSStephane Eranian csv_output ? 0 : 18, 675023695d9SStephane Eranian "<not counted>", 676023695d9SStephane Eranian csv_sep, 677023695d9SStephane Eranian csv_output ? 0 : -24, 678023695d9SStephane Eranian event_name(counter)); 679023695d9SStephane Eranian 680023695d9SStephane Eranian if (counter->cgrp) 681023695d9SStephane Eranian fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name); 682023695d9SStephane Eranian 683023695d9SStephane Eranian fputc('\n', stderr); 68442202dd5SIngo Molnar return; 68542202dd5SIngo Molnar } 68642202dd5SIngo Molnar 68742202dd5SIngo Molnar if (nsec_counter(counter)) 688f5b4a9c3SStephane Eranian nsec_printout(-1, counter, avg); 68942202dd5SIngo Molnar else 690f5b4a9c3SStephane Eranian abs_printout(-1, counter, avg); 691849abde9SPeter Zijlstra 692d7470b6aSStephane Eranian if (csv_output) { 693d7470b6aSStephane Eranian fputc('\n', stderr); 694d7470b6aSStephane Eranian return; 695d7470b6aSStephane Eranian } 696d7470b6aSStephane Eranian 697849abde9SPeter Zijlstra print_noise(counter, avg); 69842202dd5SIngo Molnar 699506d4bc8SPeter Zijlstra if (scaled) { 700506d4bc8SPeter Zijlstra double avg_enabled, avg_running; 701506d4bc8SPeter Zijlstra 70269aad6f1SArnaldo Carvalho de Melo avg_enabled = avg_stats(&ps->res_stats[1]); 70369aad6f1SArnaldo Carvalho de Melo avg_running = avg_stats(&ps->res_stats[2]); 704506d4bc8SPeter Zijlstra 705c6264defSIngo Molnar fprintf(stderr, " (%.2f%%)", 100 * avg_running / avg_enabled); 706506d4bc8SPeter Zijlstra } 70742202dd5SIngo Molnar fprintf(stderr, "\n"); 70842202dd5SIngo Molnar } 70942202dd5SIngo Molnar 710f5b4a9c3SStephane Eranian /* 711f5b4a9c3SStephane Eranian * Print out the results of a single counter: 712f5b4a9c3SStephane Eranian * does not use aggregated count in system-wide 713f5b4a9c3SStephane Eranian */ 71469aad6f1SArnaldo Carvalho de Melo static void print_counter(struct perf_evsel *counter) 715f5b4a9c3SStephane Eranian { 716f5b4a9c3SStephane Eranian u64 ena, run, val; 717f5b4a9c3SStephane Eranian int cpu; 718f5b4a9c3SStephane Eranian 7197e2ed097SArnaldo Carvalho de Melo for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 720c52b12edSArnaldo Carvalho de Melo val = counter->counts->cpu[cpu].val; 721c52b12edSArnaldo Carvalho de Melo ena = counter->counts->cpu[cpu].ena; 722c52b12edSArnaldo Carvalho de Melo run = counter->counts->cpu[cpu].run; 723f5b4a9c3SStephane Eranian if (run == 0 || ena == 0) { 724023695d9SStephane Eranian fprintf(stderr, "CPU%*d%s%*s%s%*s", 725d7470b6aSStephane Eranian csv_output ? 0 : -4, 7267e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep, 727d7470b6aSStephane Eranian csv_output ? 0 : 18, 728d7470b6aSStephane Eranian "<not counted>", csv_sep, 729023695d9SStephane Eranian csv_output ? 0 : -24, 730d7470b6aSStephane Eranian event_name(counter)); 731f5b4a9c3SStephane Eranian 732023695d9SStephane Eranian if (counter->cgrp) 733023695d9SStephane Eranian fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name); 734023695d9SStephane Eranian 735023695d9SStephane Eranian fputc('\n', stderr); 736f5b4a9c3SStephane Eranian continue; 737f5b4a9c3SStephane Eranian } 738f5b4a9c3SStephane Eranian 739f5b4a9c3SStephane Eranian if (nsec_counter(counter)) 740f5b4a9c3SStephane Eranian nsec_printout(cpu, counter, val); 741f5b4a9c3SStephane Eranian else 742f5b4a9c3SStephane Eranian abs_printout(cpu, counter, val); 743f5b4a9c3SStephane Eranian 744d7470b6aSStephane Eranian if (!csv_output) { 745f5b4a9c3SStephane Eranian print_noise(counter, 1.0); 746f5b4a9c3SStephane Eranian 747c6264defSIngo Molnar if (run != ena) 748c6264defSIngo Molnar fprintf(stderr, " (%.2f%%)", 100.0 * run / ena); 749d7470b6aSStephane Eranian } 750023695d9SStephane Eranian fputc('\n', stderr); 751f5b4a9c3SStephane Eranian } 752f5b4a9c3SStephane Eranian } 753f5b4a9c3SStephane Eranian 75442202dd5SIngo Molnar static void print_stat(int argc, const char **argv) 75542202dd5SIngo Molnar { 75669aad6f1SArnaldo Carvalho de Melo struct perf_evsel *counter; 75769aad6f1SArnaldo Carvalho de Melo int i; 75842202dd5SIngo Molnar 75986470930SIngo Molnar fflush(stdout); 76086470930SIngo Molnar 761d7470b6aSStephane Eranian if (!csv_output) { 76286470930SIngo Molnar fprintf(stderr, "\n"); 76360666c63SLiming Wang fprintf(stderr, " Performance counter stats for "); 764d6d901c2SZhang, Yanmin if(target_pid == -1 && target_tid == -1) { 76560666c63SLiming Wang fprintf(stderr, "\'%s", argv[0]); 76686470930SIngo Molnar for (i = 1; i < argc; i++) 76786470930SIngo Molnar fprintf(stderr, " %s", argv[i]); 768d6d901c2SZhang, Yanmin } else if (target_pid != -1) 769d6d901c2SZhang, Yanmin fprintf(stderr, "process id \'%d", target_pid); 770d6d901c2SZhang, Yanmin else 771d6d901c2SZhang, Yanmin fprintf(stderr, "thread id \'%d", target_tid); 77286470930SIngo Molnar 77342202dd5SIngo Molnar fprintf(stderr, "\'"); 77442202dd5SIngo Molnar if (run_count > 1) 77542202dd5SIngo Molnar fprintf(stderr, " (%d runs)", run_count); 77642202dd5SIngo Molnar fprintf(stderr, ":\n\n"); 777d7470b6aSStephane Eranian } 77886470930SIngo Molnar 779f5b4a9c3SStephane Eranian if (no_aggr) { 780361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) 78186470930SIngo Molnar print_counter(counter); 782f5b4a9c3SStephane Eranian } else { 783361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) 784f5b4a9c3SStephane Eranian print_counter_aggr(counter); 785f5b4a9c3SStephane Eranian } 78686470930SIngo Molnar 787d7470b6aSStephane Eranian if (!csv_output) { 78886470930SIngo Molnar fprintf(stderr, "\n"); 7895af52b51SStephane Eranian fprintf(stderr, " %18.9f seconds time elapsed", 790506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)/1e9); 791566747e6SIngo Molnar if (run_count > 1) { 792f99844cbSIngo Molnar print_noise_pct(stddev_stats(&walltime_nsecs_stats), 793506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)); 794566747e6SIngo Molnar } 795566747e6SIngo Molnar fprintf(stderr, "\n\n"); 79686470930SIngo Molnar } 797d7470b6aSStephane Eranian } 79886470930SIngo Molnar 799f7b7c26eSPeter Zijlstra static volatile int signr = -1; 800f7b7c26eSPeter Zijlstra 80186470930SIngo Molnar static void skip_signal(int signo) 80286470930SIngo Molnar { 8036be2850eSZhang, Yanmin if(child_pid == -1) 80460666c63SLiming Wang done = 1; 80560666c63SLiming Wang 806f7b7c26eSPeter Zijlstra signr = signo; 807f7b7c26eSPeter Zijlstra } 808f7b7c26eSPeter Zijlstra 809f7b7c26eSPeter Zijlstra static void sig_atexit(void) 810f7b7c26eSPeter Zijlstra { 811933da83aSChris Wilson if (child_pid != -1) 812933da83aSChris Wilson kill(child_pid, SIGTERM); 813933da83aSChris Wilson 814f7b7c26eSPeter Zijlstra if (signr == -1) 815f7b7c26eSPeter Zijlstra return; 816f7b7c26eSPeter Zijlstra 817f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 818f7b7c26eSPeter Zijlstra kill(getpid(), signr); 81986470930SIngo Molnar } 82086470930SIngo Molnar 82186470930SIngo Molnar static const char * const stat_usage[] = { 82260666c63SLiming Wang "perf stat [<options>] [<command>]", 82386470930SIngo Molnar NULL 82486470930SIngo Molnar }; 82586470930SIngo Molnar 826d7470b6aSStephane Eranian static int stat__set_big_num(const struct option *opt __used, 827d7470b6aSStephane Eranian const char *s __used, int unset) 828d7470b6aSStephane Eranian { 829d7470b6aSStephane Eranian big_num_opt = unset ? 0 : 1; 830d7470b6aSStephane Eranian return 0; 831d7470b6aSStephane Eranian } 832d7470b6aSStephane Eranian 83386470930SIngo Molnar static const struct option options[] = { 834361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &evsel_list, "event", 83586470930SIngo Molnar "event selector. use 'perf list' to list available events", 83686470930SIngo Molnar parse_events), 837cfd748aeSFrederic Weisbecker OPT_CALLBACK(0, "filter", &evsel_list, "filter", 838cfd748aeSFrederic Weisbecker "event filter", parse_filter), 8392e6cdf99SStephane Eranian OPT_BOOLEAN('i', "no-inherit", &no_inherit, 8402e6cdf99SStephane Eranian "child tasks do not inherit counters"), 84186470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 842d6d901c2SZhang, Yanmin "stat events on existing process id"), 843d6d901c2SZhang, Yanmin OPT_INTEGER('t', "tid", &target_tid, 844d6d901c2SZhang, Yanmin "stat events on existing thread id"), 84586470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 84686470930SIngo Molnar "system-wide collection from all CPUs"), 847b26bc5a7SBrice Goglin OPT_BOOLEAN('c', "scale", &scale, 84886470930SIngo Molnar "scale/normalize counters"), 849c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 850743ee1f8SIngo Molnar "be more verbose (show counter open errors, etc)"), 85142202dd5SIngo Molnar OPT_INTEGER('r', "repeat", &run_count, 85242202dd5SIngo Molnar "repeat command and print average + stddev (max: 100)"), 8530cfb7a13SIngo Molnar OPT_BOOLEAN('n', "null", &null_run, 8540cfb7a13SIngo Molnar "null run - dont start any counters"), 855c6264defSIngo Molnar OPT_BOOLEAN('d', "detailed", &detailed_run, 856c6264defSIngo Molnar "detailed run - start a lot of events"), 857f9cef0a9SIngo Molnar OPT_BOOLEAN('S', "sync", &sync_run, 858f9cef0a9SIngo Molnar "call sync() before starting a run"), 859d7470b6aSStephane Eranian OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 860d7470b6aSStephane Eranian "print large numbers with thousands\' separators", 861d7470b6aSStephane Eranian stat__set_big_num), 862c45c6ea2SStephane Eranian OPT_STRING('C', "cpu", &cpu_list, "cpu", 863c45c6ea2SStephane Eranian "list of cpus to monitor in system-wide"), 864f5b4a9c3SStephane Eranian OPT_BOOLEAN('A', "no-aggr", &no_aggr, 865f5b4a9c3SStephane Eranian "disable CPU count aggregation"), 866d7470b6aSStephane Eranian OPT_STRING('x', "field-separator", &csv_sep, "separator", 867d7470b6aSStephane Eranian "print counts with custom separator"), 868023695d9SStephane Eranian OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 869023695d9SStephane Eranian "monitor event in cgroup name only", 870023695d9SStephane Eranian parse_cgroups), 87186470930SIngo Molnar OPT_END() 87286470930SIngo Molnar }; 87386470930SIngo Molnar 874f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used) 87586470930SIngo Molnar { 87669aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 87769aad6f1SArnaldo Carvalho de Melo int status = -ENOMEM; 87842202dd5SIngo Molnar 8795af52b51SStephane Eranian setlocale(LC_ALL, ""); 8805af52b51SStephane Eranian 8817e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 882361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 883361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 884361c99a6SArnaldo Carvalho de Melo 885a0541234SAnton Blanchard argc = parse_options(argc, argv, options, stat_usage, 886a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 887d7470b6aSStephane Eranian 888d7470b6aSStephane Eranian if (csv_sep) 889d7470b6aSStephane Eranian csv_output = true; 890d7470b6aSStephane Eranian else 891d7470b6aSStephane Eranian csv_sep = DEFAULT_SEPARATOR; 892d7470b6aSStephane Eranian 893d7470b6aSStephane Eranian /* 894d7470b6aSStephane Eranian * let the spreadsheet do the pretty-printing 895d7470b6aSStephane Eranian */ 896d7470b6aSStephane Eranian if (csv_output) { 897d7470b6aSStephane Eranian /* User explicitely passed -B? */ 898d7470b6aSStephane Eranian if (big_num_opt == 1) { 899d7470b6aSStephane Eranian fprintf(stderr, "-B option not supported with -x\n"); 900d7470b6aSStephane Eranian usage_with_options(stat_usage, options); 901d7470b6aSStephane Eranian } else /* Nope, so disable big number formatting */ 902d7470b6aSStephane Eranian big_num = false; 903d7470b6aSStephane Eranian } else if (big_num_opt == 0) /* User passed --no-big-num */ 904d7470b6aSStephane Eranian big_num = false; 905d7470b6aSStephane Eranian 906d6d901c2SZhang, Yanmin if (!argc && target_pid == -1 && target_tid == -1) 90786470930SIngo Molnar usage_with_options(stat_usage, options); 9089e9772c4SPeter Zijlstra if (run_count <= 0) 90942202dd5SIngo Molnar usage_with_options(stat_usage, options); 91086470930SIngo Molnar 911023695d9SStephane Eranian /* no_aggr, cgroup are for system-wide only */ 912023695d9SStephane Eranian if ((no_aggr || nr_cgroups) && !system_wide) { 913023695d9SStephane Eranian fprintf(stderr, "both cgroup and no-aggregation " 914023695d9SStephane Eranian "modes only available in system-wide mode\n"); 915023695d9SStephane Eranian 916f5b4a9c3SStephane Eranian usage_with_options(stat_usage, options); 917023695d9SStephane Eranian } 918f5b4a9c3SStephane Eranian 919c3043569SJaswinder Singh Rajput /* Set attrs and nr_counters if no event is selected and !null_run */ 920c6264defSIngo Molnar if (detailed_run) { 921c6264defSIngo Molnar size_t c; 922c6264defSIngo Molnar 923c6264defSIngo Molnar for (c = 0; c < ARRAY_SIZE(detailed_attrs); ++c) { 924c6264defSIngo Molnar pos = perf_evsel__new(&detailed_attrs[c], c); 925c6264defSIngo Molnar if (pos == NULL) 926c6264defSIngo Molnar goto out; 927c6264defSIngo Molnar perf_evlist__add(evsel_list, pos); 928c6264defSIngo Molnar } 929c6264defSIngo Molnar } 930c6264defSIngo Molnar /* Set attrs and nr_counters if no event is selected and !null_run */ 931c6264defSIngo Molnar if (!detailed_run && !null_run && !evsel_list->nr_entries) { 93269aad6f1SArnaldo Carvalho de Melo size_t c; 93369aad6f1SArnaldo Carvalho de Melo 93469aad6f1SArnaldo Carvalho de Melo for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) { 935361c99a6SArnaldo Carvalho de Melo pos = perf_evsel__new(&default_attrs[c], c); 93669aad6f1SArnaldo Carvalho de Melo if (pos == NULL) 93769aad6f1SArnaldo Carvalho de Melo goto out; 938361c99a6SArnaldo Carvalho de Melo perf_evlist__add(evsel_list, pos); 93969aad6f1SArnaldo Carvalho de Melo } 940c3043569SJaswinder Singh Rajput } 94186470930SIngo Molnar 9425c98d466SArnaldo Carvalho de Melo if (target_pid != -1) 9435c98d466SArnaldo Carvalho de Melo target_tid = target_pid; 9445c98d466SArnaldo Carvalho de Melo 9457e2ed097SArnaldo Carvalho de Melo evsel_list->threads = thread_map__new(target_pid, target_tid); 9467e2ed097SArnaldo Carvalho de Melo if (evsel_list->threads == NULL) { 9475c98d466SArnaldo Carvalho de Melo pr_err("Problems finding threads of monitor\n"); 9485c98d466SArnaldo Carvalho de Melo usage_with_options(stat_usage, options); 9495c98d466SArnaldo Carvalho de Melo } 9505c98d466SArnaldo Carvalho de Melo 951a12b51c4SPaul Mackerras if (system_wide) 9527e2ed097SArnaldo Carvalho de Melo evsel_list->cpus = cpu_map__new(cpu_list); 953a12b51c4SPaul Mackerras else 9547e2ed097SArnaldo Carvalho de Melo evsel_list->cpus = cpu_map__dummy_new(); 95586470930SIngo Molnar 9567e2ed097SArnaldo Carvalho de Melo if (evsel_list->cpus == NULL) { 95760d567e2SArnaldo Carvalho de Melo perror("failed to parse CPUs map"); 958c45c6ea2SStephane Eranian usage_with_options(stat_usage, options); 95960d567e2SArnaldo Carvalho de Melo return -1; 96060d567e2SArnaldo Carvalho de Melo } 961c45c6ea2SStephane Eranian 962361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 963c52b12edSArnaldo Carvalho de Melo if (perf_evsel__alloc_stat_priv(pos) < 0 || 9647e2ed097SArnaldo Carvalho de Melo perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 || 9657e2ed097SArnaldo Carvalho de Melo perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0) 96669aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 967d6d901c2SZhang, Yanmin } 968d6d901c2SZhang, Yanmin 96986470930SIngo Molnar /* 97086470930SIngo Molnar * We dont want to block the signals - that would cause 97186470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 97286470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 97386470930SIngo Molnar * task, but being ignored by perf stat itself: 97486470930SIngo Molnar */ 975f7b7c26eSPeter Zijlstra atexit(sig_atexit); 97686470930SIngo Molnar signal(SIGINT, skip_signal); 97786470930SIngo Molnar signal(SIGALRM, skip_signal); 97886470930SIngo Molnar signal(SIGABRT, skip_signal); 97986470930SIngo Molnar 98042202dd5SIngo Molnar status = 0; 98142202dd5SIngo Molnar for (run_idx = 0; run_idx < run_count; run_idx++) { 98242202dd5SIngo Molnar if (run_count != 1 && verbose) 98342202dd5SIngo Molnar fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); 984f9cef0a9SIngo Molnar 985f9cef0a9SIngo Molnar if (sync_run) 986f9cef0a9SIngo Molnar sync(); 987f9cef0a9SIngo Molnar 98842202dd5SIngo Molnar status = run_perf_stat(argc, argv); 98942202dd5SIngo Molnar } 99042202dd5SIngo Molnar 991084ab9f8SArnaldo Carvalho de Melo if (status != -1) 99242202dd5SIngo Molnar print_stat(argc, argv); 99369aad6f1SArnaldo Carvalho de Melo out_free_fd: 994361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) 99569aad6f1SArnaldo Carvalho de Melo perf_evsel__free_stat_priv(pos); 9967e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 9970015e2e1SArnaldo Carvalho de Melo out: 9980015e2e1SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 99942202dd5SIngo Molnar return status; 100086470930SIngo Molnar } 1001