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 }, 691fc570adSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES }, 70f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 7112133affSTim Blechmann { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 7212133affSTim Blechmann { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES }, 73f4dbfa8fSPeter Zijlstra 7486470930SIngo Molnar }; 7586470930SIngo Molnar 76361c99a6SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 77361c99a6SArnaldo Carvalho de Melo 78c0555642SIan Munsie static bool system_wide = false; 7942202dd5SIngo Molnar static int run_idx = 0; 8042202dd5SIngo Molnar 813d632595SJaswinder Singh Rajput static int run_count = 1; 822e6cdf99SStephane Eranian static bool no_inherit = false; 83c0555642SIan Munsie static bool scale = true; 84f5b4a9c3SStephane Eranian static bool no_aggr = false; 85933da83aSChris Wilson static pid_t target_pid = -1; 86d6d901c2SZhang, Yanmin static pid_t target_tid = -1; 87933da83aSChris Wilson static pid_t child_pid = -1; 88c0555642SIan Munsie static bool null_run = false; 89201e0b06SArnaldo Carvalho de Melo static bool big_num = true; 90d7470b6aSStephane Eranian static int big_num_opt = -1; 91c45c6ea2SStephane Eranian static const char *cpu_list; 92d7470b6aSStephane Eranian static const char *csv_sep = NULL; 93d7470b6aSStephane Eranian static bool csv_output = false; 945af52b51SStephane Eranian 9560666c63SLiming Wang static volatile int done = 0; 9660666c63SLiming Wang 97506d4bc8SPeter Zijlstra struct stats 98506d4bc8SPeter Zijlstra { 998a02631aSPeter Zijlstra double n, mean, M2; 100506d4bc8SPeter Zijlstra }; 10142202dd5SIngo Molnar 10269aad6f1SArnaldo Carvalho de Melo struct perf_stat { 10369aad6f1SArnaldo Carvalho de Melo struct stats res_stats[3]; 10469aad6f1SArnaldo Carvalho de Melo }; 10569aad6f1SArnaldo Carvalho de Melo 106c52b12edSArnaldo Carvalho de Melo static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 10769aad6f1SArnaldo Carvalho de Melo { 108c52b12edSArnaldo Carvalho de Melo evsel->priv = zalloc(sizeof(struct perf_stat)); 10969aad6f1SArnaldo Carvalho de Melo return evsel->priv == NULL ? -ENOMEM : 0; 11069aad6f1SArnaldo Carvalho de Melo } 11169aad6f1SArnaldo Carvalho de Melo 11269aad6f1SArnaldo Carvalho de Melo static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 11369aad6f1SArnaldo Carvalho de Melo { 11469aad6f1SArnaldo Carvalho de Melo free(evsel->priv); 11569aad6f1SArnaldo Carvalho de Melo evsel->priv = NULL; 11669aad6f1SArnaldo Carvalho de Melo } 11769aad6f1SArnaldo Carvalho de Melo 1189e9772c4SPeter Zijlstra static void update_stats(struct stats *stats, u64 val) 1199e9772c4SPeter Zijlstra { 1208a02631aSPeter Zijlstra double delta; 1219e9772c4SPeter Zijlstra 1228a02631aSPeter Zijlstra stats->n++; 1238a02631aSPeter Zijlstra delta = val - stats->mean; 1248a02631aSPeter Zijlstra stats->mean += delta / stats->n; 1258a02631aSPeter Zijlstra stats->M2 += delta*(val - stats->mean); 1269e9772c4SPeter Zijlstra } 1279e9772c4SPeter Zijlstra 128506d4bc8SPeter Zijlstra static double avg_stats(struct stats *stats) 129506d4bc8SPeter Zijlstra { 1308a02631aSPeter Zijlstra return stats->mean; 131506d4bc8SPeter Zijlstra } 13242202dd5SIngo Molnar 133506d4bc8SPeter Zijlstra /* 13463d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance 13563d40debSPeter Zijlstra * 13663d40debSPeter Zijlstra * (\Sum n_i^2) - ((\Sum n_i)^2)/n 1378a02631aSPeter Zijlstra * s^2 = ------------------------------- 13863d40debSPeter Zijlstra * n - 1 13963d40debSPeter Zijlstra * 14063d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Stddev 14163d40debSPeter Zijlstra * 14263d40debSPeter Zijlstra * The std dev of the mean is related to the std dev by: 14363d40debSPeter Zijlstra * 14463d40debSPeter Zijlstra * s 14563d40debSPeter Zijlstra * s_mean = ------- 14663d40debSPeter Zijlstra * sqrt(n) 14763d40debSPeter Zijlstra * 148506d4bc8SPeter Zijlstra */ 149506d4bc8SPeter Zijlstra static double stddev_stats(struct stats *stats) 150506d4bc8SPeter Zijlstra { 1518a02631aSPeter Zijlstra double variance = stats->M2 / (stats->n - 1); 1528a02631aSPeter Zijlstra double variance_mean = variance / stats->n; 15342202dd5SIngo Molnar 15463d40debSPeter Zijlstra return sqrt(variance_mean); 155506d4bc8SPeter Zijlstra } 15642202dd5SIngo Molnar 157f5b4a9c3SStephane Eranian struct stats runtime_nsecs_stats[MAX_NR_CPUS]; 158f5b4a9c3SStephane Eranian struct stats runtime_cycles_stats[MAX_NR_CPUS]; 159481f988aSIngo Molnar struct stats runtime_stalled_cycles_stats[MAX_NR_CPUS]; 160f5b4a9c3SStephane Eranian struct stats runtime_branches_stats[MAX_NR_CPUS]; 161d58f4c82SIngo Molnar struct stats runtime_cacherefs_stats[MAX_NR_CPUS]; 162506d4bc8SPeter Zijlstra struct stats walltime_nsecs_stats; 16386470930SIngo Molnar 16448290609SArnaldo Carvalho de Melo static int create_perf_stat_counter(struct perf_evsel *evsel) 16586470930SIngo Molnar { 16669aad6f1SArnaldo Carvalho de Melo struct perf_event_attr *attr = &evsel->attr; 16786470930SIngo Molnar 16886470930SIngo Molnar if (scale) 16986470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 17086470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 17186470930SIngo Molnar 1722e6cdf99SStephane Eranian attr->inherit = !no_inherit; 1735d2cd909SArnaldo Carvalho de Melo 1745d2cd909SArnaldo Carvalho de Melo if (system_wide) 1755d2cd909SArnaldo Carvalho de Melo return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false); 1765d2cd909SArnaldo Carvalho de Melo 1772e6cdf99SStephane Eranian if (target_pid == -1 && target_tid == -1) { 17886470930SIngo Molnar attr->disabled = 1; 17957e7986eSPaul Mackerras attr->enable_on_exec = 1; 1806be2850eSZhang, Yanmin } 181084ab9f8SArnaldo Carvalho de Melo 1825d2cd909SArnaldo Carvalho de Melo return perf_evsel__open_per_thread(evsel, evsel_list->threads, false); 18386470930SIngo Molnar } 18486470930SIngo Molnar 18586470930SIngo Molnar /* 18686470930SIngo Molnar * Does the counter have nsecs as a unit? 18786470930SIngo Molnar */ 188daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel) 18986470930SIngo Molnar { 190daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) || 191daec78a0SArnaldo Carvalho de Melo perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 19286470930SIngo Molnar return 1; 19386470930SIngo Molnar 19486470930SIngo Molnar return 0; 19586470930SIngo Molnar } 19686470930SIngo Molnar 19786470930SIngo Molnar /* 198dcd9936aSIngo Molnar * Update various tracking values we maintain to print 199dcd9936aSIngo Molnar * more semantic information such as miss/hit ratios, 200dcd9936aSIngo Molnar * instruction rates, etc: 201dcd9936aSIngo Molnar */ 202dcd9936aSIngo Molnar static void update_shadow_stats(struct perf_evsel *counter, u64 *count) 203dcd9936aSIngo Molnar { 204dcd9936aSIngo Molnar if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 205dcd9936aSIngo Molnar update_stats(&runtime_nsecs_stats[0], count[0]); 206dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 207dcd9936aSIngo Molnar update_stats(&runtime_cycles_stats[0], count[0]); 208481f988aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES)) 209481f988aSIngo Molnar update_stats(&runtime_stalled_cycles_stats[0], count[0]); 210dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 211dcd9936aSIngo Molnar update_stats(&runtime_branches_stats[0], count[0]); 212dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 213dcd9936aSIngo Molnar update_stats(&runtime_cacherefs_stats[0], count[0]); 214dcd9936aSIngo Molnar } 215dcd9936aSIngo Molnar 216dcd9936aSIngo Molnar /* 21786470930SIngo Molnar * Read out the results of a single counter: 218f5b4a9c3SStephane Eranian * aggregate counts across CPUs in system-wide mode 21986470930SIngo Molnar */ 220c52b12edSArnaldo Carvalho de Melo static int read_counter_aggr(struct perf_evsel *counter) 22186470930SIngo Molnar { 22269aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps = counter->priv; 223c52b12edSArnaldo Carvalho de Melo u64 *count = counter->counts->aggr.values; 224c52b12edSArnaldo Carvalho de Melo int i; 22586470930SIngo Molnar 2267e2ed097SArnaldo Carvalho de Melo if (__perf_evsel__read(counter, evsel_list->cpus->nr, 2277e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr, scale) < 0) 228c52b12edSArnaldo Carvalho de Melo return -1; 2299e9772c4SPeter Zijlstra 2309e9772c4SPeter Zijlstra for (i = 0; i < 3; i++) 23169aad6f1SArnaldo Carvalho de Melo update_stats(&ps->res_stats[i], count[i]); 2329e9772c4SPeter Zijlstra 2339e9772c4SPeter Zijlstra if (verbose) { 2349486aa38SArnaldo Carvalho de Melo fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 2359486aa38SArnaldo Carvalho de Melo event_name(counter), count[0], count[1], count[2]); 2369e9772c4SPeter Zijlstra } 2379e9772c4SPeter Zijlstra 23886470930SIngo Molnar /* 23986470930SIngo Molnar * Save the full runtime - to allow normalization during printout: 24086470930SIngo Molnar */ 241dcd9936aSIngo Molnar update_shadow_stats(counter, count); 242c52b12edSArnaldo Carvalho de Melo 243c52b12edSArnaldo Carvalho de Melo return 0; 244f5b4a9c3SStephane Eranian } 245f5b4a9c3SStephane Eranian 246f5b4a9c3SStephane Eranian /* 247f5b4a9c3SStephane Eranian * Read out the results of a single counter: 248f5b4a9c3SStephane Eranian * do not aggregate counts across CPUs in system-wide mode 249f5b4a9c3SStephane Eranian */ 250c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter) 251f5b4a9c3SStephane Eranian { 252c52b12edSArnaldo Carvalho de Melo u64 *count; 253f5b4a9c3SStephane Eranian int cpu; 254f5b4a9c3SStephane Eranian 2557e2ed097SArnaldo Carvalho de Melo for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 256c52b12edSArnaldo Carvalho de Melo if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 257c52b12edSArnaldo Carvalho de Melo return -1; 258f5b4a9c3SStephane Eranian 259c52b12edSArnaldo Carvalho de Melo count = counter->counts->cpu[cpu].values; 260f5b4a9c3SStephane Eranian 261dcd9936aSIngo Molnar update_shadow_stats(counter, count); 262f5b4a9c3SStephane Eranian } 263c52b12edSArnaldo Carvalho de Melo 264c52b12edSArnaldo Carvalho de Melo return 0; 26586470930SIngo Molnar } 26686470930SIngo Molnar 267f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv) 26886470930SIngo Molnar { 26986470930SIngo Molnar unsigned long long t0, t1; 27069aad6f1SArnaldo Carvalho de Melo struct perf_evsel *counter; 27142202dd5SIngo Molnar int status = 0; 272051ae7f7SPaul Mackerras int child_ready_pipe[2], go_pipe[2]; 2736be2850eSZhang, Yanmin const bool forks = (argc > 0); 274051ae7f7SPaul Mackerras char buf; 27586470930SIngo Molnar 27660666c63SLiming Wang if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 277051ae7f7SPaul Mackerras perror("failed to create pipes"); 278051ae7f7SPaul Mackerras exit(1); 279051ae7f7SPaul Mackerras } 280051ae7f7SPaul Mackerras 28160666c63SLiming Wang if (forks) { 2826be2850eSZhang, Yanmin if ((child_pid = fork()) < 0) 283051ae7f7SPaul Mackerras perror("failed to fork"); 284051ae7f7SPaul Mackerras 2856be2850eSZhang, Yanmin if (!child_pid) { 286051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 287051ae7f7SPaul Mackerras close(go_pipe[1]); 288051ae7f7SPaul Mackerras fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 289051ae7f7SPaul Mackerras 290051ae7f7SPaul Mackerras /* 291051ae7f7SPaul Mackerras * Do a dummy execvp to get the PLT entry resolved, 292051ae7f7SPaul Mackerras * so we avoid the resolver overhead on the real 293051ae7f7SPaul Mackerras * execvp call. 294051ae7f7SPaul Mackerras */ 295051ae7f7SPaul Mackerras execvp("", (char **)argv); 296051ae7f7SPaul Mackerras 297051ae7f7SPaul Mackerras /* 298051ae7f7SPaul Mackerras * Tell the parent we're ready to go 299051ae7f7SPaul Mackerras */ 300051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 301051ae7f7SPaul Mackerras 302051ae7f7SPaul Mackerras /* 303051ae7f7SPaul Mackerras * Wait until the parent tells us to go. 304051ae7f7SPaul Mackerras */ 305a92bef0fSFrederic Weisbecker if (read(go_pipe[0], &buf, 1) == -1) 306a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 307051ae7f7SPaul Mackerras 308051ae7f7SPaul Mackerras execvp(argv[0], (char **)argv); 309051ae7f7SPaul Mackerras 310051ae7f7SPaul Mackerras perror(argv[0]); 311051ae7f7SPaul Mackerras exit(-1); 312051ae7f7SPaul Mackerras } 313051ae7f7SPaul Mackerras 314d6d901c2SZhang, Yanmin if (target_tid == -1 && target_pid == -1 && !system_wide) 3157e2ed097SArnaldo Carvalho de Melo evsel_list->threads->map[0] = child_pid; 316d6d901c2SZhang, Yanmin 317051ae7f7SPaul Mackerras /* 318051ae7f7SPaul Mackerras * Wait for the child to be ready to exec. 319051ae7f7SPaul Mackerras */ 320051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 321051ae7f7SPaul Mackerras close(go_pipe[0]); 322a92bef0fSFrederic Weisbecker if (read(child_ready_pipe[0], &buf, 1) == -1) 323a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 324051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 32560666c63SLiming Wang } 326051ae7f7SPaul Mackerras 327361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 32848290609SArnaldo Carvalho de Melo if (create_perf_stat_counter(counter) < 0) { 32948290609SArnaldo Carvalho de Melo if (errno == -EPERM || errno == -EACCES) { 330d9cf837eSCorey Ashford error("You may not have permission to collect %sstats.\n" 331d9cf837eSCorey Ashford "\t Consider tweaking" 332d9cf837eSCorey Ashford " /proc/sys/kernel/perf_event_paranoid or running as root.", 333084ab9f8SArnaldo Carvalho de Melo system_wide ? "system-wide " : ""); 3345a3446bcSDavid Ahern } else if (errno == ENOENT) { 3355a3446bcSDavid Ahern error("%s event is not supported. ", event_name(counter)); 33648290609SArnaldo Carvalho de Melo } else { 33748290609SArnaldo Carvalho de Melo error("open_counter returned with %d (%s). " 33848290609SArnaldo Carvalho de Melo "/bin/dmesg may provide additional information.\n", 33948290609SArnaldo Carvalho de Melo errno, strerror(errno)); 34048290609SArnaldo Carvalho de Melo } 341084ab9f8SArnaldo Carvalho de Melo if (child_pid != -1) 342084ab9f8SArnaldo Carvalho de Melo kill(child_pid, SIGTERM); 34348290609SArnaldo Carvalho de Melo die("Not all events could be opened.\n"); 344084ab9f8SArnaldo Carvalho de Melo return -1; 345084ab9f8SArnaldo Carvalho de Melo } 34648290609SArnaldo Carvalho de Melo } 34786470930SIngo Molnar 348cfd748aeSFrederic Weisbecker if (perf_evlist__set_filters(evsel_list)) { 349cfd748aeSFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 350cfd748aeSFrederic Weisbecker strerror(errno)); 351cfd748aeSFrederic Weisbecker return -1; 352cfd748aeSFrederic Weisbecker } 353cfd748aeSFrederic Weisbecker 35486470930SIngo Molnar /* 35586470930SIngo Molnar * Enable counters and exec the command: 35686470930SIngo Molnar */ 35786470930SIngo Molnar t0 = rdclock(); 35886470930SIngo Molnar 35960666c63SLiming Wang if (forks) { 360051ae7f7SPaul Mackerras close(go_pipe[1]); 36142202dd5SIngo Molnar wait(&status); 36260666c63SLiming Wang } else { 3636be2850eSZhang, Yanmin while(!done) sleep(1); 36460666c63SLiming Wang } 36586470930SIngo Molnar 36686470930SIngo Molnar t1 = rdclock(); 36786470930SIngo Molnar 3689e9772c4SPeter Zijlstra update_stats(&walltime_nsecs_stats, t1 - t0); 36942202dd5SIngo Molnar 370f5b4a9c3SStephane Eranian if (no_aggr) { 371361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 37242202dd5SIngo Molnar read_counter(counter); 3737e2ed097SArnaldo Carvalho de Melo perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); 374f5b4a9c3SStephane Eranian } 375c52b12edSArnaldo Carvalho de Melo } else { 376361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 377c52b12edSArnaldo Carvalho de Melo read_counter_aggr(counter); 3787e2ed097SArnaldo Carvalho de Melo perf_evsel__close_fd(counter, evsel_list->cpus->nr, 3797e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr); 380c52b12edSArnaldo Carvalho de Melo } 381c52b12edSArnaldo Carvalho de Melo } 382c52b12edSArnaldo Carvalho de Melo 38342202dd5SIngo Molnar return WEXITSTATUS(status); 38442202dd5SIngo Molnar } 38542202dd5SIngo Molnar 386f99844cbSIngo Molnar static void print_noise_pct(double total, double avg) 387f99844cbSIngo Molnar { 388f99844cbSIngo Molnar double pct = 0.0; 389f99844cbSIngo Molnar 390f99844cbSIngo Molnar if (avg) 391f99844cbSIngo Molnar pct = 100.0*total/avg; 392f99844cbSIngo Molnar 393f99844cbSIngo Molnar fprintf(stderr, " ( +-%6.2f%% )", pct); 394f99844cbSIngo Molnar } 395f99844cbSIngo Molnar 39669aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg) 39742202dd5SIngo Molnar { 39869aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps; 39969aad6f1SArnaldo Carvalho de Melo 400849abde9SPeter Zijlstra if (run_count == 1) 401849abde9SPeter Zijlstra return; 402849abde9SPeter Zijlstra 40369aad6f1SArnaldo Carvalho de Melo ps = evsel->priv; 404f99844cbSIngo Molnar print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 40542202dd5SIngo Molnar } 40642202dd5SIngo Molnar 407daec78a0SArnaldo Carvalho de Melo static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) 40842202dd5SIngo Molnar { 409506d4bc8SPeter Zijlstra double msecs = avg / 1e6; 410d7470b6aSStephane Eranian char cpustr[16] = { '\0', }; 411d7470b6aSStephane Eranian const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s"; 41242202dd5SIngo Molnar 413f5b4a9c3SStephane Eranian if (no_aggr) 414d7470b6aSStephane Eranian sprintf(cpustr, "CPU%*d%s", 415d7470b6aSStephane Eranian csv_output ? 0 : -4, 4167e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep); 417d7470b6aSStephane Eranian 418daec78a0SArnaldo Carvalho de Melo fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 419d7470b6aSStephane Eranian 420023695d9SStephane Eranian if (evsel->cgrp) 421023695d9SStephane Eranian fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name); 422023695d9SStephane Eranian 423d7470b6aSStephane Eranian if (csv_output) 424d7470b6aSStephane Eranian return; 42542202dd5SIngo Molnar 426daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 427481f988aSIngo Molnar fprintf(stderr, " # %8.3f CPUs utilized ", avg / avg_stats(&walltime_nsecs_stats)); 42842202dd5SIngo Molnar } 42942202dd5SIngo Molnar 430a5d243d0SIngo Molnar static void print_stalled_cycles(int cpu, struct perf_evsel *evsel __used, double avg) 431a5d243d0SIngo Molnar { 432a5d243d0SIngo Molnar double total, ratio = 0.0; 433a5d243d0SIngo Molnar const char *color; 434a5d243d0SIngo Molnar 435a5d243d0SIngo Molnar total = avg_stats(&runtime_cycles_stats[cpu]); 436a5d243d0SIngo Molnar 437a5d243d0SIngo Molnar if (total) 438a5d243d0SIngo Molnar ratio = avg / total * 100.0; 439a5d243d0SIngo Molnar 440a5d243d0SIngo Molnar color = PERF_COLOR_NORMAL; 441a5d243d0SIngo Molnar if (ratio > 75.0) 442a5d243d0SIngo Molnar color = PERF_COLOR_RED; 443a5d243d0SIngo Molnar else if (ratio > 50.0) 444a5d243d0SIngo Molnar color = PERF_COLOR_MAGENTA; 445a5d243d0SIngo Molnar else if (ratio > 25.0) 446a5d243d0SIngo Molnar color = PERF_COLOR_YELLOW; 447a5d243d0SIngo Molnar 448a5d243d0SIngo Molnar fprintf(stderr, " # "); 449a5d243d0SIngo Molnar color_fprintf(stderr, color, "%5.2f%%", ratio); 450a5d243d0SIngo Molnar fprintf(stderr, " of all cycles are idle "); 451a5d243d0SIngo Molnar } 452a5d243d0SIngo Molnar 453c78df6c1SIngo Molnar static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) 454c78df6c1SIngo Molnar { 455c78df6c1SIngo Molnar double total, ratio = 0.0; 456c78df6c1SIngo Molnar const char *color; 457c78df6c1SIngo Molnar 458c78df6c1SIngo Molnar total = avg_stats(&runtime_branches_stats[cpu]); 459c78df6c1SIngo Molnar 460c78df6c1SIngo Molnar if (total) 461c78df6c1SIngo Molnar ratio = avg / total * 100.0; 462c78df6c1SIngo Molnar 463c78df6c1SIngo Molnar color = PERF_COLOR_NORMAL; 464c78df6c1SIngo Molnar if (ratio > 20.0) 465c78df6c1SIngo Molnar color = PERF_COLOR_RED; 466c78df6c1SIngo Molnar else if (ratio > 10.0) 467c78df6c1SIngo Molnar color = PERF_COLOR_MAGENTA; 468c78df6c1SIngo Molnar else if (ratio > 5.0) 469c78df6c1SIngo Molnar color = PERF_COLOR_YELLOW; 470c78df6c1SIngo Molnar 471c78df6c1SIngo Molnar fprintf(stderr, " # "); 472c78df6c1SIngo Molnar color_fprintf(stderr, color, "%5.2f%%", ratio); 473c78df6c1SIngo Molnar fprintf(stderr, " of all branches "); 474c78df6c1SIngo Molnar } 475c78df6c1SIngo Molnar 476daec78a0SArnaldo Carvalho de Melo static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) 47742202dd5SIngo Molnar { 478c7f7fea3SIngo Molnar double total, ratio = 0.0; 479f5b4a9c3SStephane Eranian char cpustr[16] = { '\0', }; 480d7470b6aSStephane Eranian const char *fmt; 481d7470b6aSStephane Eranian 482d7470b6aSStephane Eranian if (csv_output) 483d7470b6aSStephane Eranian fmt = "%s%.0f%s%s"; 484d7470b6aSStephane Eranian else if (big_num) 485d7470b6aSStephane Eranian fmt = "%s%'18.0f%s%-24s"; 486d7470b6aSStephane Eranian else 487d7470b6aSStephane Eranian fmt = "%s%18.0f%s%-24s"; 488f5b4a9c3SStephane Eranian 489f5b4a9c3SStephane Eranian if (no_aggr) 490d7470b6aSStephane Eranian sprintf(cpustr, "CPU%*d%s", 491d7470b6aSStephane Eranian csv_output ? 0 : -4, 4927e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep); 493f5b4a9c3SStephane Eranian else 494f5b4a9c3SStephane Eranian cpu = 0; 495c7f7fea3SIngo Molnar 496daec78a0SArnaldo Carvalho de Melo fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel)); 497d7470b6aSStephane Eranian 498023695d9SStephane Eranian if (evsel->cgrp) 499023695d9SStephane Eranian fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name); 500023695d9SStephane Eranian 501d7470b6aSStephane Eranian if (csv_output) 502d7470b6aSStephane Eranian return; 50342202dd5SIngo Molnar 504daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 505f5b4a9c3SStephane Eranian total = avg_stats(&runtime_cycles_stats[cpu]); 506c7f7fea3SIngo Molnar 507c7f7fea3SIngo Molnar if (total) 508c7f7fea3SIngo Molnar ratio = avg / total; 509c7f7fea3SIngo Molnar 510481f988aSIngo Molnar fprintf(stderr, " # %4.2f insns per cycle", ratio); 511481f988aSIngo Molnar 512481f988aSIngo Molnar total = avg_stats(&runtime_stalled_cycles_stats[cpu]); 513481f988aSIngo Molnar 514481f988aSIngo Molnar if (total && avg) { 515481f988aSIngo Molnar ratio = total / avg; 516481f988aSIngo Molnar fprintf(stderr, "\n # %4.2f stalled cycles per insn", ratio); 517481f988aSIngo Molnar } 518481f988aSIngo Molnar 519daec78a0SArnaldo Carvalho de Melo } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && 520f5b4a9c3SStephane Eranian runtime_branches_stats[cpu].n != 0) { 521c78df6c1SIngo Molnar print_branch_misses(cpu, evsel, avg); 522d58f4c82SIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) && 523d58f4c82SIngo Molnar runtime_cacherefs_stats[cpu].n != 0) { 524d58f4c82SIngo Molnar total = avg_stats(&runtime_cacherefs_stats[cpu]); 525d58f4c82SIngo Molnar 526d58f4c82SIngo Molnar if (total) 527d58f4c82SIngo Molnar ratio = avg * 100 / total; 528d58f4c82SIngo Molnar 529481f988aSIngo Molnar fprintf(stderr, " # %8.3f %% of all cache refs ", ratio); 530d58f4c82SIngo Molnar 53111ba2b85SIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES)) { 532a5d243d0SIngo Molnar print_stalled_cycles(cpu, evsel, avg); 533481f988aSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 534481f988aSIngo Molnar total = avg_stats(&runtime_nsecs_stats[cpu]); 535481f988aSIngo Molnar 536481f988aSIngo Molnar if (total) 537481f988aSIngo Molnar ratio = 1.0 * avg / total; 538481f988aSIngo Molnar 539481f988aSIngo Molnar fprintf(stderr, " # %8.3f GHz ", ratio); 540481f988aSIngo Molnar } else if (runtime_nsecs_stats[cpu].n != 0) { 541481f988aSIngo Molnar total = avg_stats(&runtime_nsecs_stats[cpu]); 542481f988aSIngo Molnar 543481f988aSIngo Molnar if (total) 544481f988aSIngo Molnar ratio = 1000.0 * avg / total; 545481f988aSIngo Molnar 546481f988aSIngo Molnar fprintf(stderr, " # %8.3f M/sec ", ratio); 547a5d243d0SIngo Molnar } else { 548a5d243d0SIngo Molnar fprintf(stderr, " "); 54942202dd5SIngo Molnar } 55042202dd5SIngo Molnar } 55142202dd5SIngo Molnar 55242202dd5SIngo Molnar /* 55342202dd5SIngo Molnar * Print out the results of a single counter: 554f5b4a9c3SStephane Eranian * aggregated counts in system-wide mode 55542202dd5SIngo Molnar */ 55669aad6f1SArnaldo Carvalho de Melo static void print_counter_aggr(struct perf_evsel *counter) 55742202dd5SIngo Molnar { 55869aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps = counter->priv; 55969aad6f1SArnaldo Carvalho de Melo double avg = avg_stats(&ps->res_stats[0]); 560c52b12edSArnaldo Carvalho de Melo int scaled = counter->counts->scaled; 56142202dd5SIngo Molnar 56242202dd5SIngo Molnar if (scaled == -1) { 563023695d9SStephane Eranian fprintf(stderr, "%*s%s%*s", 564d7470b6aSStephane Eranian csv_output ? 0 : 18, 565023695d9SStephane Eranian "<not counted>", 566023695d9SStephane Eranian csv_sep, 567023695d9SStephane Eranian csv_output ? 0 : -24, 568023695d9SStephane Eranian event_name(counter)); 569023695d9SStephane Eranian 570023695d9SStephane Eranian if (counter->cgrp) 571023695d9SStephane Eranian fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name); 572023695d9SStephane Eranian 573023695d9SStephane Eranian fputc('\n', stderr); 57442202dd5SIngo Molnar return; 57542202dd5SIngo Molnar } 57642202dd5SIngo Molnar 57742202dd5SIngo Molnar if (nsec_counter(counter)) 578f5b4a9c3SStephane Eranian nsec_printout(-1, counter, avg); 57942202dd5SIngo Molnar else 580f5b4a9c3SStephane Eranian abs_printout(-1, counter, avg); 581849abde9SPeter Zijlstra 582d7470b6aSStephane Eranian if (csv_output) { 583d7470b6aSStephane Eranian fputc('\n', stderr); 584d7470b6aSStephane Eranian return; 585d7470b6aSStephane Eranian } 586d7470b6aSStephane Eranian 587849abde9SPeter Zijlstra print_noise(counter, avg); 58842202dd5SIngo Molnar 589506d4bc8SPeter Zijlstra if (scaled) { 590506d4bc8SPeter Zijlstra double avg_enabled, avg_running; 591506d4bc8SPeter Zijlstra 59269aad6f1SArnaldo Carvalho de Melo avg_enabled = avg_stats(&ps->res_stats[1]); 59369aad6f1SArnaldo Carvalho de Melo avg_running = avg_stats(&ps->res_stats[2]); 594506d4bc8SPeter Zijlstra 595210ad39fSIngo Molnar fprintf(stderr, " (scaled from %.2f%%)", 596506d4bc8SPeter Zijlstra 100 * avg_running / avg_enabled); 597506d4bc8SPeter Zijlstra } 59842202dd5SIngo Molnar fprintf(stderr, "\n"); 59942202dd5SIngo Molnar } 60042202dd5SIngo Molnar 601f5b4a9c3SStephane Eranian /* 602f5b4a9c3SStephane Eranian * Print out the results of a single counter: 603f5b4a9c3SStephane Eranian * does not use aggregated count in system-wide 604f5b4a9c3SStephane Eranian */ 60569aad6f1SArnaldo Carvalho de Melo static void print_counter(struct perf_evsel *counter) 606f5b4a9c3SStephane Eranian { 607f5b4a9c3SStephane Eranian u64 ena, run, val; 608f5b4a9c3SStephane Eranian int cpu; 609f5b4a9c3SStephane Eranian 6107e2ed097SArnaldo Carvalho de Melo for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 611c52b12edSArnaldo Carvalho de Melo val = counter->counts->cpu[cpu].val; 612c52b12edSArnaldo Carvalho de Melo ena = counter->counts->cpu[cpu].ena; 613c52b12edSArnaldo Carvalho de Melo run = counter->counts->cpu[cpu].run; 614f5b4a9c3SStephane Eranian if (run == 0 || ena == 0) { 615023695d9SStephane Eranian fprintf(stderr, "CPU%*d%s%*s%s%*s", 616d7470b6aSStephane Eranian csv_output ? 0 : -4, 6177e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep, 618d7470b6aSStephane Eranian csv_output ? 0 : 18, 619d7470b6aSStephane Eranian "<not counted>", csv_sep, 620023695d9SStephane Eranian csv_output ? 0 : -24, 621d7470b6aSStephane Eranian event_name(counter)); 622f5b4a9c3SStephane Eranian 623023695d9SStephane Eranian if (counter->cgrp) 624023695d9SStephane Eranian fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name); 625023695d9SStephane Eranian 626023695d9SStephane Eranian fputc('\n', stderr); 627f5b4a9c3SStephane Eranian continue; 628f5b4a9c3SStephane Eranian } 629f5b4a9c3SStephane Eranian 630f5b4a9c3SStephane Eranian if (nsec_counter(counter)) 631f5b4a9c3SStephane Eranian nsec_printout(cpu, counter, val); 632f5b4a9c3SStephane Eranian else 633f5b4a9c3SStephane Eranian abs_printout(cpu, counter, val); 634f5b4a9c3SStephane Eranian 635d7470b6aSStephane Eranian if (!csv_output) { 636f5b4a9c3SStephane Eranian print_noise(counter, 1.0); 637f5b4a9c3SStephane Eranian 638f5b4a9c3SStephane Eranian if (run != ena) { 639f5b4a9c3SStephane Eranian fprintf(stderr, " (scaled from %.2f%%)", 640f5b4a9c3SStephane Eranian 100.0 * run / ena); 641f5b4a9c3SStephane Eranian } 642d7470b6aSStephane Eranian } 643023695d9SStephane Eranian fputc('\n', stderr); 644f5b4a9c3SStephane Eranian } 645f5b4a9c3SStephane Eranian } 646f5b4a9c3SStephane Eranian 64742202dd5SIngo Molnar static void print_stat(int argc, const char **argv) 64842202dd5SIngo Molnar { 64969aad6f1SArnaldo Carvalho de Melo struct perf_evsel *counter; 65069aad6f1SArnaldo Carvalho de Melo int i; 65142202dd5SIngo Molnar 65286470930SIngo Molnar fflush(stdout); 65386470930SIngo Molnar 654d7470b6aSStephane Eranian if (!csv_output) { 65586470930SIngo Molnar fprintf(stderr, "\n"); 65660666c63SLiming Wang fprintf(stderr, " Performance counter stats for "); 657d6d901c2SZhang, Yanmin if(target_pid == -1 && target_tid == -1) { 65860666c63SLiming Wang fprintf(stderr, "\'%s", argv[0]); 65986470930SIngo Molnar for (i = 1; i < argc; i++) 66086470930SIngo Molnar fprintf(stderr, " %s", argv[i]); 661d6d901c2SZhang, Yanmin } else if (target_pid != -1) 662d6d901c2SZhang, Yanmin fprintf(stderr, "process id \'%d", target_pid); 663d6d901c2SZhang, Yanmin else 664d6d901c2SZhang, Yanmin fprintf(stderr, "thread id \'%d", target_tid); 66586470930SIngo Molnar 66642202dd5SIngo Molnar fprintf(stderr, "\'"); 66742202dd5SIngo Molnar if (run_count > 1) 66842202dd5SIngo Molnar fprintf(stderr, " (%d runs)", run_count); 66942202dd5SIngo Molnar fprintf(stderr, ":\n\n"); 670d7470b6aSStephane Eranian } 67186470930SIngo Molnar 672f5b4a9c3SStephane Eranian if (no_aggr) { 673361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) 67486470930SIngo Molnar print_counter(counter); 675f5b4a9c3SStephane Eranian } else { 676361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) 677f5b4a9c3SStephane Eranian print_counter_aggr(counter); 678f5b4a9c3SStephane Eranian } 67986470930SIngo Molnar 680d7470b6aSStephane Eranian if (!csv_output) { 68186470930SIngo Molnar fprintf(stderr, "\n"); 6825af52b51SStephane Eranian fprintf(stderr, " %18.9f seconds time elapsed", 683506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)/1e9); 684566747e6SIngo Molnar if (run_count > 1) { 685f99844cbSIngo Molnar print_noise_pct(stddev_stats(&walltime_nsecs_stats), 686506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)); 687566747e6SIngo Molnar } 688566747e6SIngo Molnar fprintf(stderr, "\n\n"); 68986470930SIngo Molnar } 690d7470b6aSStephane Eranian } 69186470930SIngo Molnar 692f7b7c26eSPeter Zijlstra static volatile int signr = -1; 693f7b7c26eSPeter Zijlstra 69486470930SIngo Molnar static void skip_signal(int signo) 69586470930SIngo Molnar { 6966be2850eSZhang, Yanmin if(child_pid == -1) 69760666c63SLiming Wang done = 1; 69860666c63SLiming Wang 699f7b7c26eSPeter Zijlstra signr = signo; 700f7b7c26eSPeter Zijlstra } 701f7b7c26eSPeter Zijlstra 702f7b7c26eSPeter Zijlstra static void sig_atexit(void) 703f7b7c26eSPeter Zijlstra { 704933da83aSChris Wilson if (child_pid != -1) 705933da83aSChris Wilson kill(child_pid, SIGTERM); 706933da83aSChris Wilson 707f7b7c26eSPeter Zijlstra if (signr == -1) 708f7b7c26eSPeter Zijlstra return; 709f7b7c26eSPeter Zijlstra 710f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 711f7b7c26eSPeter Zijlstra kill(getpid(), signr); 71286470930SIngo Molnar } 71386470930SIngo Molnar 71486470930SIngo Molnar static const char * const stat_usage[] = { 71560666c63SLiming Wang "perf stat [<options>] [<command>]", 71686470930SIngo Molnar NULL 71786470930SIngo Molnar }; 71886470930SIngo Molnar 719d7470b6aSStephane Eranian static int stat__set_big_num(const struct option *opt __used, 720d7470b6aSStephane Eranian const char *s __used, int unset) 721d7470b6aSStephane Eranian { 722d7470b6aSStephane Eranian big_num_opt = unset ? 0 : 1; 723d7470b6aSStephane Eranian return 0; 724d7470b6aSStephane Eranian } 725d7470b6aSStephane Eranian 72686470930SIngo Molnar static const struct option options[] = { 727361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &evsel_list, "event", 72886470930SIngo Molnar "event selector. use 'perf list' to list available events", 72986470930SIngo Molnar parse_events), 730cfd748aeSFrederic Weisbecker OPT_CALLBACK(0, "filter", &evsel_list, "filter", 731cfd748aeSFrederic Weisbecker "event filter", parse_filter), 7322e6cdf99SStephane Eranian OPT_BOOLEAN('i', "no-inherit", &no_inherit, 7332e6cdf99SStephane Eranian "child tasks do not inherit counters"), 73486470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 735d6d901c2SZhang, Yanmin "stat events on existing process id"), 736d6d901c2SZhang, Yanmin OPT_INTEGER('t', "tid", &target_tid, 737d6d901c2SZhang, Yanmin "stat events on existing thread id"), 73886470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 73986470930SIngo Molnar "system-wide collection from all CPUs"), 740b26bc5a7SBrice Goglin OPT_BOOLEAN('c', "scale", &scale, 74186470930SIngo Molnar "scale/normalize counters"), 742c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 743743ee1f8SIngo Molnar "be more verbose (show counter open errors, etc)"), 74442202dd5SIngo Molnar OPT_INTEGER('r', "repeat", &run_count, 74542202dd5SIngo Molnar "repeat command and print average + stddev (max: 100)"), 7460cfb7a13SIngo Molnar OPT_BOOLEAN('n', "null", &null_run, 7470cfb7a13SIngo Molnar "null run - dont start any counters"), 748d7470b6aSStephane Eranian OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 749d7470b6aSStephane Eranian "print large numbers with thousands\' separators", 750d7470b6aSStephane Eranian stat__set_big_num), 751c45c6ea2SStephane Eranian OPT_STRING('C', "cpu", &cpu_list, "cpu", 752c45c6ea2SStephane Eranian "list of cpus to monitor in system-wide"), 753f5b4a9c3SStephane Eranian OPT_BOOLEAN('A', "no-aggr", &no_aggr, 754f5b4a9c3SStephane Eranian "disable CPU count aggregation"), 755d7470b6aSStephane Eranian OPT_STRING('x', "field-separator", &csv_sep, "separator", 756d7470b6aSStephane Eranian "print counts with custom separator"), 757023695d9SStephane Eranian OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 758023695d9SStephane Eranian "monitor event in cgroup name only", 759023695d9SStephane Eranian parse_cgroups), 76086470930SIngo Molnar OPT_END() 76186470930SIngo Molnar }; 76286470930SIngo Molnar 763f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used) 76486470930SIngo Molnar { 76569aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 76669aad6f1SArnaldo Carvalho de Melo int status = -ENOMEM; 76742202dd5SIngo Molnar 7685af52b51SStephane Eranian setlocale(LC_ALL, ""); 7695af52b51SStephane Eranian 7707e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 771361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 772361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 773361c99a6SArnaldo Carvalho de Melo 774a0541234SAnton Blanchard argc = parse_options(argc, argv, options, stat_usage, 775a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 776d7470b6aSStephane Eranian 777d7470b6aSStephane Eranian if (csv_sep) 778d7470b6aSStephane Eranian csv_output = true; 779d7470b6aSStephane Eranian else 780d7470b6aSStephane Eranian csv_sep = DEFAULT_SEPARATOR; 781d7470b6aSStephane Eranian 782d7470b6aSStephane Eranian /* 783d7470b6aSStephane Eranian * let the spreadsheet do the pretty-printing 784d7470b6aSStephane Eranian */ 785d7470b6aSStephane Eranian if (csv_output) { 786d7470b6aSStephane Eranian /* User explicitely passed -B? */ 787d7470b6aSStephane Eranian if (big_num_opt == 1) { 788d7470b6aSStephane Eranian fprintf(stderr, "-B option not supported with -x\n"); 789d7470b6aSStephane Eranian usage_with_options(stat_usage, options); 790d7470b6aSStephane Eranian } else /* Nope, so disable big number formatting */ 791d7470b6aSStephane Eranian big_num = false; 792d7470b6aSStephane Eranian } else if (big_num_opt == 0) /* User passed --no-big-num */ 793d7470b6aSStephane Eranian big_num = false; 794d7470b6aSStephane Eranian 795d6d901c2SZhang, Yanmin if (!argc && target_pid == -1 && target_tid == -1) 79686470930SIngo Molnar usage_with_options(stat_usage, options); 7979e9772c4SPeter Zijlstra if (run_count <= 0) 79842202dd5SIngo Molnar usage_with_options(stat_usage, options); 79986470930SIngo Molnar 800023695d9SStephane Eranian /* no_aggr, cgroup are for system-wide only */ 801023695d9SStephane Eranian if ((no_aggr || nr_cgroups) && !system_wide) { 802023695d9SStephane Eranian fprintf(stderr, "both cgroup and no-aggregation " 803023695d9SStephane Eranian "modes only available in system-wide mode\n"); 804023695d9SStephane Eranian 805f5b4a9c3SStephane Eranian usage_with_options(stat_usage, options); 806023695d9SStephane Eranian } 807f5b4a9c3SStephane Eranian 808c3043569SJaswinder Singh Rajput /* Set attrs and nr_counters if no event is selected and !null_run */ 809361c99a6SArnaldo Carvalho de Melo if (!null_run && !evsel_list->nr_entries) { 81069aad6f1SArnaldo Carvalho de Melo size_t c; 81169aad6f1SArnaldo Carvalho de Melo 81269aad6f1SArnaldo Carvalho de Melo for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) { 813361c99a6SArnaldo Carvalho de Melo pos = perf_evsel__new(&default_attrs[c], c); 81469aad6f1SArnaldo Carvalho de Melo if (pos == NULL) 81569aad6f1SArnaldo Carvalho de Melo goto out; 816361c99a6SArnaldo Carvalho de Melo perf_evlist__add(evsel_list, pos); 81769aad6f1SArnaldo Carvalho de Melo } 818c3043569SJaswinder Singh Rajput } 81986470930SIngo Molnar 8205c98d466SArnaldo Carvalho de Melo if (target_pid != -1) 8215c98d466SArnaldo Carvalho de Melo target_tid = target_pid; 8225c98d466SArnaldo Carvalho de Melo 8237e2ed097SArnaldo Carvalho de Melo evsel_list->threads = thread_map__new(target_pid, target_tid); 8247e2ed097SArnaldo Carvalho de Melo if (evsel_list->threads == NULL) { 8255c98d466SArnaldo Carvalho de Melo pr_err("Problems finding threads of monitor\n"); 8265c98d466SArnaldo Carvalho de Melo usage_with_options(stat_usage, options); 8275c98d466SArnaldo Carvalho de Melo } 8285c98d466SArnaldo Carvalho de Melo 829a12b51c4SPaul Mackerras if (system_wide) 8307e2ed097SArnaldo Carvalho de Melo evsel_list->cpus = cpu_map__new(cpu_list); 831a12b51c4SPaul Mackerras else 8327e2ed097SArnaldo Carvalho de Melo evsel_list->cpus = cpu_map__dummy_new(); 83386470930SIngo Molnar 8347e2ed097SArnaldo Carvalho de Melo if (evsel_list->cpus == NULL) { 83560d567e2SArnaldo Carvalho de Melo perror("failed to parse CPUs map"); 836c45c6ea2SStephane Eranian usage_with_options(stat_usage, options); 83760d567e2SArnaldo Carvalho de Melo return -1; 83860d567e2SArnaldo Carvalho de Melo } 839c45c6ea2SStephane Eranian 840361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 841c52b12edSArnaldo Carvalho de Melo if (perf_evsel__alloc_stat_priv(pos) < 0 || 8427e2ed097SArnaldo Carvalho de Melo perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 || 8437e2ed097SArnaldo Carvalho de Melo perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0) 84469aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 845d6d901c2SZhang, Yanmin } 846d6d901c2SZhang, Yanmin 84786470930SIngo Molnar /* 84886470930SIngo Molnar * We dont want to block the signals - that would cause 84986470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 85086470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 85186470930SIngo Molnar * task, but being ignored by perf stat itself: 85286470930SIngo Molnar */ 853f7b7c26eSPeter Zijlstra atexit(sig_atexit); 85486470930SIngo Molnar signal(SIGINT, skip_signal); 85586470930SIngo Molnar signal(SIGALRM, skip_signal); 85686470930SIngo Molnar signal(SIGABRT, skip_signal); 85786470930SIngo Molnar 85842202dd5SIngo Molnar status = 0; 85942202dd5SIngo Molnar for (run_idx = 0; run_idx < run_count; run_idx++) { 86042202dd5SIngo Molnar if (run_count != 1 && verbose) 86142202dd5SIngo Molnar fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); 86242202dd5SIngo Molnar status = run_perf_stat(argc, argv); 86342202dd5SIngo Molnar } 86442202dd5SIngo Molnar 865084ab9f8SArnaldo Carvalho de Melo if (status != -1) 86642202dd5SIngo Molnar print_stat(argc, argv); 86769aad6f1SArnaldo Carvalho de Melo out_free_fd: 868361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) 86969aad6f1SArnaldo Carvalho de Melo perf_evsel__free_stat_priv(pos); 8707e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 8710015e2e1SArnaldo Carvalho de Melo out: 8720015e2e1SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 87342202dd5SIngo Molnar return status; 87486470930SIngo Molnar } 875