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 92cba3ffbSIngo Molnar $ perf stat ./hackbench 10 1086470930SIngo Molnar 112cba3ffbSIngo Molnar Time: 0.118 1286470930SIngo Molnar 132cba3ffbSIngo Molnar Performance counter stats for './hackbench 10': 1486470930SIngo Molnar 152cba3ffbSIngo Molnar 1708.761321 task-clock # 11.037 CPUs utilized 162cba3ffbSIngo Molnar 41,190 context-switches # 0.024 M/sec 172cba3ffbSIngo Molnar 6,735 CPU-migrations # 0.004 M/sec 182cba3ffbSIngo Molnar 17,318 page-faults # 0.010 M/sec 192cba3ffbSIngo Molnar 5,205,202,243 cycles # 3.046 GHz 202cba3ffbSIngo Molnar 3,856,436,920 stalled-cycles-frontend # 74.09% frontend cycles idle 212cba3ffbSIngo Molnar 1,600,790,871 stalled-cycles-backend # 30.75% backend cycles idle 222cba3ffbSIngo Molnar 2,603,501,247 instructions # 0.50 insns per cycle 232cba3ffbSIngo Molnar # 1.48 stalled cycles per insn 242cba3ffbSIngo Molnar 484,357,498 branches # 283.455 M/sec 252cba3ffbSIngo Molnar 6,388,934 branch-misses # 1.32% of all branches 262cba3ffbSIngo Molnar 272cba3ffbSIngo Molnar 0.154822978 seconds time elapsed 2886470930SIngo Molnar 2986470930SIngo Molnar * 302cba3ffbSIngo Molnar * Copyright (C) 2008-2011, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 3186470930SIngo Molnar * 3286470930SIngo Molnar * Improvements and fixes by: 3386470930SIngo Molnar * 3486470930SIngo Molnar * Arjan van de Ven <arjan@linux.intel.com> 3586470930SIngo Molnar * Yanmin Zhang <yanmin.zhang@intel.com> 3686470930SIngo Molnar * Wu Fengguang <fengguang.wu@intel.com> 3786470930SIngo Molnar * Mike Galbraith <efault@gmx.de> 3886470930SIngo Molnar * Paul Mackerras <paulus@samba.org> 396e750a8fSJaswinder Singh Rajput * Jaswinder Singh Rajput <jaswinder@kernel.org> 4086470930SIngo Molnar * 4186470930SIngo Molnar * Released under the GPL v2. (and only v2, not any later version) 4286470930SIngo Molnar */ 4386470930SIngo Molnar 4486470930SIngo Molnar #include "perf.h" 4586470930SIngo Molnar #include "builtin.h" 4686470930SIngo Molnar #include "util/util.h" 4786470930SIngo Molnar #include "util/parse-options.h" 4886470930SIngo Molnar #include "util/parse-events.h" 498f28827aSFrederic Weisbecker #include "util/event.h" 50361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 5169aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 528f28827aSFrederic Weisbecker #include "util/debug.h" 53a5d243d0SIngo Molnar #include "util/color.h" 5460666c63SLiming Wang #include "util/header.h" 55a12b51c4SPaul Mackerras #include "util/cpumap.h" 56d6d901c2SZhang, Yanmin #include "util/thread.h" 57fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 5886470930SIngo Molnar 5986470930SIngo Molnar #include <sys/prctl.h> 6042202dd5SIngo Molnar #include <math.h> 615af52b51SStephane Eranian #include <locale.h> 6286470930SIngo Molnar 63d7470b6aSStephane Eranian #define DEFAULT_SEPARATOR " " 642cee77c4SDavid Ahern #define CNTR_NOT_SUPPORTED "<not supported>" 652cee77c4SDavid Ahern #define CNTR_NOT_COUNTED "<not counted>" 66d7470b6aSStephane Eranian 67cdd6c482SIngo Molnar static struct perf_event_attr default_attrs[] = { 6886470930SIngo Molnar 69f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 70f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES }, 71f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 72f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 7386470930SIngo Molnar 74f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 75129c04cbSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 76129c04cbSIngo Molnar { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 77f4dbfa8fSPeter Zijlstra { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 7812133affSTim Blechmann { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 7912133affSTim Blechmann { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES }, 80f4dbfa8fSPeter Zijlstra 8186470930SIngo Molnar }; 8286470930SIngo Molnar 83c6264defSIngo Molnar /* 842cba3ffbSIngo Molnar * Detailed stats (-d), covering the L1 and last level data caches: 85c6264defSIngo Molnar */ 86c6264defSIngo Molnar static struct perf_event_attr detailed_attrs[] = { 87c6264defSIngo Molnar 88c6264defSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 89c6264defSIngo Molnar .config = 90c6264defSIngo Molnar PERF_COUNT_HW_CACHE_L1D << 0 | 91c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 92c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 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_MISS << 16) }, 99c6264defSIngo Molnar 100c6264defSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 101c6264defSIngo Molnar .config = 102c6264defSIngo Molnar PERF_COUNT_HW_CACHE_LL << 0 | 103c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 104c6264defSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 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_MISS << 16) }, 111c6264defSIngo Molnar }; 112c6264defSIngo Molnar 1132cba3ffbSIngo Molnar /* 1142cba3ffbSIngo Molnar * Very detailed stats (-d -d), covering the instruction cache and the TLB caches: 1152cba3ffbSIngo Molnar */ 1162cba3ffbSIngo Molnar static struct perf_event_attr very_detailed_attrs[] = { 1172cba3ffbSIngo Molnar 1182cba3ffbSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 1192cba3ffbSIngo Molnar .config = 1202cba3ffbSIngo Molnar PERF_COUNT_HW_CACHE_L1I << 0 | 1212cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1222cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1232cba3ffbSIngo Molnar 1242cba3ffbSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 1252cba3ffbSIngo Molnar .config = 1262cba3ffbSIngo Molnar PERF_COUNT_HW_CACHE_L1I << 0 | 1272cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1282cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1292cba3ffbSIngo Molnar 1302cba3ffbSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 1312cba3ffbSIngo Molnar .config = 1322cba3ffbSIngo Molnar PERF_COUNT_HW_CACHE_DTLB << 0 | 1332cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1342cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1352cba3ffbSIngo Molnar 1362cba3ffbSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 1372cba3ffbSIngo Molnar .config = 1382cba3ffbSIngo Molnar PERF_COUNT_HW_CACHE_DTLB << 0 | 1392cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1402cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1412cba3ffbSIngo Molnar 1422cba3ffbSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 1432cba3ffbSIngo Molnar .config = 1442cba3ffbSIngo Molnar PERF_COUNT_HW_CACHE_ITLB << 0 | 1452cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1462cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1472cba3ffbSIngo Molnar 1482cba3ffbSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 1492cba3ffbSIngo Molnar .config = 1502cba3ffbSIngo Molnar PERF_COUNT_HW_CACHE_ITLB << 0 | 1512cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1522cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1532cba3ffbSIngo Molnar 1542cba3ffbSIngo Molnar }; 1552cba3ffbSIngo Molnar 1562cba3ffbSIngo Molnar /* 1572cba3ffbSIngo Molnar * Very, very detailed stats (-d -d -d), adding prefetch events: 1582cba3ffbSIngo Molnar */ 1592cba3ffbSIngo Molnar static struct perf_event_attr very_very_detailed_attrs[] = { 1602cba3ffbSIngo Molnar 1612cba3ffbSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 1622cba3ffbSIngo Molnar .config = 1632cba3ffbSIngo Molnar PERF_COUNT_HW_CACHE_L1D << 0 | 1642cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 1652cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1662cba3ffbSIngo Molnar 1672cba3ffbSIngo Molnar { .type = PERF_TYPE_HW_CACHE, 1682cba3ffbSIngo Molnar .config = 1692cba3ffbSIngo Molnar PERF_COUNT_HW_CACHE_L1D << 0 | 1702cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 1712cba3ffbSIngo Molnar (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1722cba3ffbSIngo Molnar }; 1732cba3ffbSIngo Molnar 1742cba3ffbSIngo Molnar 1752cba3ffbSIngo Molnar 176666e6d48SRobert Richter static struct perf_evlist *evsel_list; 177361c99a6SArnaldo Carvalho de Melo 17820f946b4SNamhyung Kim static struct perf_target target; 17942202dd5SIngo Molnar 18020f946b4SNamhyung Kim static int run_idx = 0; 1813d632595SJaswinder Singh Rajput static int run_count = 1; 1822e6cdf99SStephane Eranian static bool no_inherit = false; 183c0555642SIan Munsie static bool scale = true; 184f5b4a9c3SStephane Eranian static bool no_aggr = false; 185933da83aSChris Wilson static pid_t child_pid = -1; 186c0555642SIan Munsie static bool null_run = false; 1872cba3ffbSIngo Molnar static int detailed_run = 0; 188f9cef0a9SIngo Molnar static bool sync_run = false; 189201e0b06SArnaldo Carvalho de Melo static bool big_num = true; 190d7470b6aSStephane Eranian static int big_num_opt = -1; 191d7470b6aSStephane Eranian static const char *csv_sep = NULL; 192d7470b6aSStephane Eranian static bool csv_output = false; 19343bece79SLin Ming static bool group = false; 1944aa9015fSStephane Eranian static const char *output_name = NULL; 1954aa9015fSStephane Eranian static FILE *output = NULL; 19656f3bae7SJim Cromie static int output_fd; 1975af52b51SStephane Eranian 19860666c63SLiming Wang static volatile int done = 0; 19960666c63SLiming Wang 200506d4bc8SPeter Zijlstra struct stats 201506d4bc8SPeter Zijlstra { 2028a02631aSPeter Zijlstra double n, mean, M2; 203506d4bc8SPeter Zijlstra }; 20442202dd5SIngo Molnar 20569aad6f1SArnaldo Carvalho de Melo struct perf_stat { 20669aad6f1SArnaldo Carvalho de Melo struct stats res_stats[3]; 20769aad6f1SArnaldo Carvalho de Melo }; 20869aad6f1SArnaldo Carvalho de Melo 209c52b12edSArnaldo Carvalho de Melo static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 21069aad6f1SArnaldo Carvalho de Melo { 211c52b12edSArnaldo Carvalho de Melo evsel->priv = zalloc(sizeof(struct perf_stat)); 21269aad6f1SArnaldo Carvalho de Melo return evsel->priv == NULL ? -ENOMEM : 0; 21369aad6f1SArnaldo Carvalho de Melo } 21469aad6f1SArnaldo Carvalho de Melo 21569aad6f1SArnaldo Carvalho de Melo static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 21669aad6f1SArnaldo Carvalho de Melo { 21769aad6f1SArnaldo Carvalho de Melo free(evsel->priv); 21869aad6f1SArnaldo Carvalho de Melo evsel->priv = NULL; 21969aad6f1SArnaldo Carvalho de Melo } 22069aad6f1SArnaldo Carvalho de Melo 2219e9772c4SPeter Zijlstra static void update_stats(struct stats *stats, u64 val) 2229e9772c4SPeter Zijlstra { 2238a02631aSPeter Zijlstra double delta; 2249e9772c4SPeter Zijlstra 2258a02631aSPeter Zijlstra stats->n++; 2268a02631aSPeter Zijlstra delta = val - stats->mean; 2278a02631aSPeter Zijlstra stats->mean += delta / stats->n; 2288a02631aSPeter Zijlstra stats->M2 += delta*(val - stats->mean); 2299e9772c4SPeter Zijlstra } 2309e9772c4SPeter Zijlstra 231506d4bc8SPeter Zijlstra static double avg_stats(struct stats *stats) 232506d4bc8SPeter Zijlstra { 2338a02631aSPeter Zijlstra return stats->mean; 234506d4bc8SPeter Zijlstra } 23542202dd5SIngo Molnar 236506d4bc8SPeter Zijlstra /* 23763d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance 23863d40debSPeter Zijlstra * 23963d40debSPeter Zijlstra * (\Sum n_i^2) - ((\Sum n_i)^2)/n 2408a02631aSPeter Zijlstra * s^2 = ------------------------------- 24163d40debSPeter Zijlstra * n - 1 24263d40debSPeter Zijlstra * 24363d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Stddev 24463d40debSPeter Zijlstra * 24563d40debSPeter Zijlstra * The std dev of the mean is related to the std dev by: 24663d40debSPeter Zijlstra * 24763d40debSPeter Zijlstra * s 24863d40debSPeter Zijlstra * s_mean = ------- 24963d40debSPeter Zijlstra * sqrt(n) 25063d40debSPeter Zijlstra * 251506d4bc8SPeter Zijlstra */ 252506d4bc8SPeter Zijlstra static double stddev_stats(struct stats *stats) 253506d4bc8SPeter Zijlstra { 25419f47402SJim Cromie double variance, variance_mean; 25519f47402SJim Cromie 25619f47402SJim Cromie if (!stats->n) 25719f47402SJim Cromie return 0.0; 25819f47402SJim Cromie 25919f47402SJim Cromie variance = stats->M2 / (stats->n - 1); 26019f47402SJim Cromie variance_mean = variance / stats->n; 26142202dd5SIngo Molnar 26263d40debSPeter Zijlstra return sqrt(variance_mean); 263506d4bc8SPeter Zijlstra } 26442202dd5SIngo Molnar 265666e6d48SRobert Richter static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; 266666e6d48SRobert Richter static struct stats runtime_cycles_stats[MAX_NR_CPUS]; 267666e6d48SRobert Richter static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS]; 268666e6d48SRobert Richter static struct stats runtime_stalled_cycles_back_stats[MAX_NR_CPUS]; 269666e6d48SRobert Richter static struct stats runtime_branches_stats[MAX_NR_CPUS]; 270666e6d48SRobert Richter static struct stats runtime_cacherefs_stats[MAX_NR_CPUS]; 271666e6d48SRobert Richter static struct stats runtime_l1_dcache_stats[MAX_NR_CPUS]; 272666e6d48SRobert Richter static struct stats runtime_l1_icache_stats[MAX_NR_CPUS]; 273666e6d48SRobert Richter static struct stats runtime_ll_cache_stats[MAX_NR_CPUS]; 274666e6d48SRobert Richter static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS]; 275666e6d48SRobert Richter static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; 276666e6d48SRobert Richter static struct stats walltime_nsecs_stats; 27786470930SIngo Molnar 278727ab04eSArnaldo Carvalho de Melo static int create_perf_stat_counter(struct perf_evsel *evsel, 279727ab04eSArnaldo Carvalho de Melo struct perf_evsel *first) 28086470930SIngo Molnar { 28169aad6f1SArnaldo Carvalho de Melo struct perf_event_attr *attr = &evsel->attr; 282727ab04eSArnaldo Carvalho de Melo struct xyarray *group_fd = NULL; 283727ab04eSArnaldo Carvalho de Melo 284727ab04eSArnaldo Carvalho de Melo if (group && evsel != first) 285727ab04eSArnaldo Carvalho de Melo group_fd = first->fd; 28686470930SIngo Molnar 28786470930SIngo Molnar if (scale) 28886470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 28986470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 29086470930SIngo Molnar 2912e6cdf99SStephane Eranian attr->inherit = !no_inherit; 2925d2cd909SArnaldo Carvalho de Melo 293d67356e7SNamhyung Kim if (!perf_target__no_cpu(&target)) 294727ab04eSArnaldo Carvalho de Melo return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, 295727ab04eSArnaldo Carvalho de Melo group, group_fd); 296d67356e7SNamhyung Kim if (perf_target__no_task(&target) && (!group || evsel == first)) { 29786470930SIngo Molnar attr->disabled = 1; 29857e7986eSPaul Mackerras attr->enable_on_exec = 1; 2996be2850eSZhang, Yanmin } 300084ab9f8SArnaldo Carvalho de Melo 301727ab04eSArnaldo Carvalho de Melo return perf_evsel__open_per_thread(evsel, evsel_list->threads, 302727ab04eSArnaldo Carvalho de Melo group, group_fd); 30386470930SIngo Molnar } 30486470930SIngo Molnar 30586470930SIngo Molnar /* 30686470930SIngo Molnar * Does the counter have nsecs as a unit? 30786470930SIngo Molnar */ 308daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel) 30986470930SIngo Molnar { 310daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) || 311daec78a0SArnaldo Carvalho de Melo perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 31286470930SIngo Molnar return 1; 31386470930SIngo Molnar 31486470930SIngo Molnar return 0; 31586470930SIngo Molnar } 31686470930SIngo Molnar 31786470930SIngo Molnar /* 318dcd9936aSIngo Molnar * Update various tracking values we maintain to print 319dcd9936aSIngo Molnar * more semantic information such as miss/hit ratios, 320dcd9936aSIngo Molnar * instruction rates, etc: 321dcd9936aSIngo Molnar */ 322dcd9936aSIngo Molnar static void update_shadow_stats(struct perf_evsel *counter, u64 *count) 323dcd9936aSIngo Molnar { 324dcd9936aSIngo Molnar if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 325dcd9936aSIngo Molnar update_stats(&runtime_nsecs_stats[0], count[0]); 326dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 327dcd9936aSIngo Molnar update_stats(&runtime_cycles_stats[0], count[0]); 328d3d1e86dSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 329d3d1e86dSIngo Molnar update_stats(&runtime_stalled_cycles_front_stats[0], count[0]); 330129c04cbSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 331d3d1e86dSIngo Molnar update_stats(&runtime_stalled_cycles_back_stats[0], count[0]); 332dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 333dcd9936aSIngo Molnar update_stats(&runtime_branches_stats[0], count[0]); 334dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 335dcd9936aSIngo Molnar update_stats(&runtime_cacherefs_stats[0], count[0]); 3368bb6c79fSIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) 3378bb6c79fSIngo Molnar update_stats(&runtime_l1_dcache_stats[0], count[0]); 338c3305257SIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) 339c3305257SIngo Molnar update_stats(&runtime_l1_icache_stats[0], count[0]); 340c3305257SIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) 341c3305257SIngo Molnar update_stats(&runtime_ll_cache_stats[0], count[0]); 342c3305257SIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) 343c3305257SIngo Molnar update_stats(&runtime_dtlb_cache_stats[0], count[0]); 344c3305257SIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 345c3305257SIngo Molnar update_stats(&runtime_itlb_cache_stats[0], count[0]); 346dcd9936aSIngo Molnar } 347dcd9936aSIngo Molnar 348dcd9936aSIngo Molnar /* 34986470930SIngo Molnar * Read out the results of a single counter: 350f5b4a9c3SStephane Eranian * aggregate counts across CPUs in system-wide mode 35186470930SIngo Molnar */ 352c52b12edSArnaldo Carvalho de Melo static int read_counter_aggr(struct perf_evsel *counter) 35386470930SIngo Molnar { 35469aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps = counter->priv; 355c52b12edSArnaldo Carvalho de Melo u64 *count = counter->counts->aggr.values; 356c52b12edSArnaldo Carvalho de Melo int i; 35786470930SIngo Molnar 3587e2ed097SArnaldo Carvalho de Melo if (__perf_evsel__read(counter, evsel_list->cpus->nr, 3597e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr, scale) < 0) 360c52b12edSArnaldo Carvalho de Melo return -1; 3619e9772c4SPeter Zijlstra 3629e9772c4SPeter Zijlstra for (i = 0; i < 3; i++) 36369aad6f1SArnaldo Carvalho de Melo update_stats(&ps->res_stats[i], count[i]); 3649e9772c4SPeter Zijlstra 3659e9772c4SPeter Zijlstra if (verbose) { 3664aa9015fSStephane Eranian fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 3679486aa38SArnaldo Carvalho de Melo event_name(counter), count[0], count[1], count[2]); 3689e9772c4SPeter Zijlstra } 3699e9772c4SPeter Zijlstra 37086470930SIngo Molnar /* 37186470930SIngo Molnar * Save the full runtime - to allow normalization during printout: 37286470930SIngo Molnar */ 373dcd9936aSIngo Molnar update_shadow_stats(counter, count); 374c52b12edSArnaldo Carvalho de Melo 375c52b12edSArnaldo Carvalho de Melo return 0; 376f5b4a9c3SStephane Eranian } 377f5b4a9c3SStephane Eranian 378f5b4a9c3SStephane Eranian /* 379f5b4a9c3SStephane Eranian * Read out the results of a single counter: 380f5b4a9c3SStephane Eranian * do not aggregate counts across CPUs in system-wide mode 381f5b4a9c3SStephane Eranian */ 382c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter) 383f5b4a9c3SStephane Eranian { 384c52b12edSArnaldo Carvalho de Melo u64 *count; 385f5b4a9c3SStephane Eranian int cpu; 386f5b4a9c3SStephane Eranian 3877e2ed097SArnaldo Carvalho de Melo for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 388c52b12edSArnaldo Carvalho de Melo if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 389c52b12edSArnaldo Carvalho de Melo return -1; 390f5b4a9c3SStephane Eranian 391c52b12edSArnaldo Carvalho de Melo count = counter->counts->cpu[cpu].values; 392f5b4a9c3SStephane Eranian 393dcd9936aSIngo Molnar update_shadow_stats(counter, count); 394f5b4a9c3SStephane Eranian } 395c52b12edSArnaldo Carvalho de Melo 396c52b12edSArnaldo Carvalho de Melo return 0; 39786470930SIngo Molnar } 39886470930SIngo Molnar 399f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv) 40086470930SIngo Molnar { 40186470930SIngo Molnar unsigned long long t0, t1; 402727ab04eSArnaldo Carvalho de Melo struct perf_evsel *counter, *first; 40342202dd5SIngo Molnar int status = 0; 404051ae7f7SPaul Mackerras int child_ready_pipe[2], go_pipe[2]; 4056be2850eSZhang, Yanmin const bool forks = (argc > 0); 406051ae7f7SPaul Mackerras char buf; 40786470930SIngo Molnar 40860666c63SLiming Wang if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 409051ae7f7SPaul Mackerras perror("failed to create pipes"); 410051ae7f7SPaul Mackerras exit(1); 411051ae7f7SPaul Mackerras } 412051ae7f7SPaul Mackerras 41360666c63SLiming Wang if (forks) { 4146be2850eSZhang, Yanmin if ((child_pid = fork()) < 0) 415051ae7f7SPaul Mackerras perror("failed to fork"); 416051ae7f7SPaul Mackerras 4176be2850eSZhang, Yanmin if (!child_pid) { 418051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 419051ae7f7SPaul Mackerras close(go_pipe[1]); 420051ae7f7SPaul Mackerras fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 421051ae7f7SPaul Mackerras 422051ae7f7SPaul Mackerras /* 423051ae7f7SPaul Mackerras * Do a dummy execvp to get the PLT entry resolved, 424051ae7f7SPaul Mackerras * so we avoid the resolver overhead on the real 425051ae7f7SPaul Mackerras * execvp call. 426051ae7f7SPaul Mackerras */ 427051ae7f7SPaul Mackerras execvp("", (char **)argv); 428051ae7f7SPaul Mackerras 429051ae7f7SPaul Mackerras /* 430051ae7f7SPaul Mackerras * Tell the parent we're ready to go 431051ae7f7SPaul Mackerras */ 432051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 433051ae7f7SPaul Mackerras 434051ae7f7SPaul Mackerras /* 435051ae7f7SPaul Mackerras * Wait until the parent tells us to go. 436051ae7f7SPaul Mackerras */ 437a92bef0fSFrederic Weisbecker if (read(go_pipe[0], &buf, 1) == -1) 438a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 439051ae7f7SPaul Mackerras 440051ae7f7SPaul Mackerras execvp(argv[0], (char **)argv); 441051ae7f7SPaul Mackerras 442051ae7f7SPaul Mackerras perror(argv[0]); 443051ae7f7SPaul Mackerras exit(-1); 444051ae7f7SPaul Mackerras } 445051ae7f7SPaul Mackerras 446d67356e7SNamhyung Kim if (perf_target__none(&target)) 4477e2ed097SArnaldo Carvalho de Melo evsel_list->threads->map[0] = child_pid; 448d6d901c2SZhang, Yanmin 449051ae7f7SPaul Mackerras /* 450051ae7f7SPaul Mackerras * Wait for the child to be ready to exec. 451051ae7f7SPaul Mackerras */ 452051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 453051ae7f7SPaul Mackerras close(go_pipe[0]); 454a92bef0fSFrederic Weisbecker if (read(child_ready_pipe[0], &buf, 1) == -1) 455a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 456051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 45760666c63SLiming Wang } 458051ae7f7SPaul Mackerras 459727ab04eSArnaldo Carvalho de Melo first = list_entry(evsel_list->entries.next, struct perf_evsel, node); 460727ab04eSArnaldo Carvalho de Melo 461361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 462727ab04eSArnaldo Carvalho de Melo if (create_perf_stat_counter(counter, first) < 0) { 46338f6ae1eSAnton Blanchard if (errno == EINVAL || errno == ENOSYS || 46438f6ae1eSAnton Blanchard errno == ENOENT || errno == EOPNOTSUPP) { 465c63ca0c0SDavid Ahern if (verbose) 466c63ca0c0SDavid Ahern ui__warning("%s event is not supported by the kernel.\n", 467c63ca0c0SDavid Ahern event_name(counter)); 4682cee77c4SDavid Ahern counter->supported = false; 469ede70290SIngo Molnar continue; 470c63ca0c0SDavid Ahern } 471ede70290SIngo Molnar 472ede70290SIngo Molnar if (errno == EPERM || errno == EACCES) { 473d9cf837eSCorey Ashford error("You may not have permission to collect %sstats.\n" 474d9cf837eSCorey Ashford "\t Consider tweaking" 475d9cf837eSCorey Ashford " /proc/sys/kernel/perf_event_paranoid or running as root.", 47620f946b4SNamhyung Kim target.system_wide ? "system-wide " : ""); 47748290609SArnaldo Carvalho de Melo } else { 47848290609SArnaldo Carvalho de Melo error("open_counter returned with %d (%s). " 47948290609SArnaldo Carvalho de Melo "/bin/dmesg may provide additional information.\n", 48048290609SArnaldo Carvalho de Melo errno, strerror(errno)); 48148290609SArnaldo Carvalho de Melo } 482084ab9f8SArnaldo Carvalho de Melo if (child_pid != -1) 483084ab9f8SArnaldo Carvalho de Melo kill(child_pid, SIGTERM); 48448290609SArnaldo Carvalho de Melo die("Not all events could be opened.\n"); 485084ab9f8SArnaldo Carvalho de Melo return -1; 486084ab9f8SArnaldo Carvalho de Melo } 4872cee77c4SDavid Ahern counter->supported = true; 48848290609SArnaldo Carvalho de Melo } 48986470930SIngo Molnar 490cfd748aeSFrederic Weisbecker if (perf_evlist__set_filters(evsel_list)) { 491cfd748aeSFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 492cfd748aeSFrederic Weisbecker strerror(errno)); 493cfd748aeSFrederic Weisbecker return -1; 494cfd748aeSFrederic Weisbecker } 495cfd748aeSFrederic Weisbecker 49686470930SIngo Molnar /* 49786470930SIngo Molnar * Enable counters and exec the command: 49886470930SIngo Molnar */ 49986470930SIngo Molnar t0 = rdclock(); 50086470930SIngo Molnar 50160666c63SLiming Wang if (forks) { 502051ae7f7SPaul Mackerras close(go_pipe[1]); 50342202dd5SIngo Molnar wait(&status); 50433e49ea7SAndi Kleen if (WIFSIGNALED(status)) 50533e49ea7SAndi Kleen psignal(WTERMSIG(status), argv[0]); 50660666c63SLiming Wang } else { 5076be2850eSZhang, Yanmin while(!done) sleep(1); 50860666c63SLiming Wang } 50986470930SIngo Molnar 51086470930SIngo Molnar t1 = rdclock(); 51186470930SIngo Molnar 5129e9772c4SPeter Zijlstra update_stats(&walltime_nsecs_stats, t1 - t0); 51342202dd5SIngo Molnar 514f5b4a9c3SStephane Eranian if (no_aggr) { 515361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 51642202dd5SIngo Molnar read_counter(counter); 5177e2ed097SArnaldo Carvalho de Melo perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); 518f5b4a9c3SStephane Eranian } 519c52b12edSArnaldo Carvalho de Melo } else { 520361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 521c52b12edSArnaldo Carvalho de Melo read_counter_aggr(counter); 5227e2ed097SArnaldo Carvalho de Melo perf_evsel__close_fd(counter, evsel_list->cpus->nr, 5237e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr); 524c52b12edSArnaldo Carvalho de Melo } 525c52b12edSArnaldo Carvalho de Melo } 526c52b12edSArnaldo Carvalho de Melo 52742202dd5SIngo Molnar return WEXITSTATUS(status); 52842202dd5SIngo Molnar } 52942202dd5SIngo Molnar 530f99844cbSIngo Molnar static void print_noise_pct(double total, double avg) 531f99844cbSIngo Molnar { 532f99844cbSIngo Molnar double pct = 0.0; 533f99844cbSIngo Molnar 534f99844cbSIngo Molnar if (avg) 535f99844cbSIngo Molnar pct = 100.0*total/avg; 536f99844cbSIngo Molnar 5373ae9a34dSZhengyu He if (csv_output) 5384aa9015fSStephane Eranian fprintf(output, "%s%.2f%%", csv_sep, pct); 539a1bca6ccSJim Cromie else if (pct) 5404aa9015fSStephane Eranian fprintf(output, " ( +-%6.2f%% )", pct); 541f99844cbSIngo Molnar } 542f99844cbSIngo Molnar 54369aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg) 54442202dd5SIngo Molnar { 54569aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps; 54669aad6f1SArnaldo Carvalho de Melo 547849abde9SPeter Zijlstra if (run_count == 1) 548849abde9SPeter Zijlstra return; 549849abde9SPeter Zijlstra 55069aad6f1SArnaldo Carvalho de Melo ps = evsel->priv; 551f99844cbSIngo Molnar print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 55242202dd5SIngo Molnar } 55342202dd5SIngo Molnar 554daec78a0SArnaldo Carvalho de Melo static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) 55542202dd5SIngo Molnar { 556506d4bc8SPeter Zijlstra double msecs = avg / 1e6; 557d7470b6aSStephane Eranian char cpustr[16] = { '\0', }; 5582cba3ffbSIngo Molnar const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s"; 55942202dd5SIngo Molnar 560f5b4a9c3SStephane Eranian if (no_aggr) 561d7470b6aSStephane Eranian sprintf(cpustr, "CPU%*d%s", 562d7470b6aSStephane Eranian csv_output ? 0 : -4, 5637e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep); 564d7470b6aSStephane Eranian 5654aa9015fSStephane Eranian fprintf(output, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 566d7470b6aSStephane Eranian 567023695d9SStephane Eranian if (evsel->cgrp) 5684aa9015fSStephane Eranian fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 569023695d9SStephane Eranian 570d7470b6aSStephane Eranian if (csv_output) 571d7470b6aSStephane Eranian return; 57242202dd5SIngo Molnar 573daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 5744aa9015fSStephane Eranian fprintf(output, " # %8.3f CPUs utilized ", 5754aa9015fSStephane Eranian avg / avg_stats(&walltime_nsecs_stats)); 5769dac6a29SNamhyung Kim else 5779dac6a29SNamhyung Kim fprintf(output, " "); 57842202dd5SIngo Molnar } 57942202dd5SIngo Molnar 58015e6392fSNamhyung Kim /* used for get_ratio_color() */ 58115e6392fSNamhyung Kim enum grc_type { 58215e6392fSNamhyung Kim GRC_STALLED_CYCLES_FE, 58315e6392fSNamhyung Kim GRC_STALLED_CYCLES_BE, 58415e6392fSNamhyung Kim GRC_CACHE_MISSES, 58515e6392fSNamhyung Kim GRC_MAX_NR 58615e6392fSNamhyung Kim }; 58715e6392fSNamhyung Kim 58815e6392fSNamhyung Kim static const char *get_ratio_color(enum grc_type type, double ratio) 58915e6392fSNamhyung Kim { 59015e6392fSNamhyung Kim static const double grc_table[GRC_MAX_NR][3] = { 59115e6392fSNamhyung Kim [GRC_STALLED_CYCLES_FE] = { 50.0, 30.0, 10.0 }, 59215e6392fSNamhyung Kim [GRC_STALLED_CYCLES_BE] = { 75.0, 50.0, 20.0 }, 59315e6392fSNamhyung Kim [GRC_CACHE_MISSES] = { 20.0, 10.0, 5.0 }, 59415e6392fSNamhyung Kim }; 59515e6392fSNamhyung Kim const char *color = PERF_COLOR_NORMAL; 59615e6392fSNamhyung Kim 59715e6392fSNamhyung Kim if (ratio > grc_table[type][0]) 59815e6392fSNamhyung Kim color = PERF_COLOR_RED; 59915e6392fSNamhyung Kim else if (ratio > grc_table[type][1]) 60015e6392fSNamhyung Kim color = PERF_COLOR_MAGENTA; 60115e6392fSNamhyung Kim else if (ratio > grc_table[type][2]) 60215e6392fSNamhyung Kim color = PERF_COLOR_YELLOW; 60315e6392fSNamhyung Kim 60415e6392fSNamhyung Kim return color; 60515e6392fSNamhyung Kim } 60615e6392fSNamhyung Kim 607d3d1e86dSIngo Molnar static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) 608d3d1e86dSIngo Molnar { 609d3d1e86dSIngo Molnar double total, ratio = 0.0; 610d3d1e86dSIngo Molnar const char *color; 611d3d1e86dSIngo Molnar 612d3d1e86dSIngo Molnar total = avg_stats(&runtime_cycles_stats[cpu]); 613d3d1e86dSIngo Molnar 614d3d1e86dSIngo Molnar if (total) 615d3d1e86dSIngo Molnar ratio = avg / total * 100.0; 616d3d1e86dSIngo Molnar 61715e6392fSNamhyung Kim color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio); 618d3d1e86dSIngo Molnar 6194aa9015fSStephane Eranian fprintf(output, " # "); 6204aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 6214aa9015fSStephane Eranian fprintf(output, " frontend cycles idle "); 622d3d1e86dSIngo Molnar } 623d3d1e86dSIngo Molnar 624d3d1e86dSIngo Molnar static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) 625a5d243d0SIngo Molnar { 626a5d243d0SIngo Molnar double total, ratio = 0.0; 627a5d243d0SIngo Molnar const char *color; 628a5d243d0SIngo Molnar 629a5d243d0SIngo Molnar total = avg_stats(&runtime_cycles_stats[cpu]); 630a5d243d0SIngo Molnar 631a5d243d0SIngo Molnar if (total) 632a5d243d0SIngo Molnar ratio = avg / total * 100.0; 633a5d243d0SIngo Molnar 63415e6392fSNamhyung Kim color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); 635a5d243d0SIngo Molnar 6364aa9015fSStephane Eranian fprintf(output, " # "); 6374aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 6384aa9015fSStephane Eranian fprintf(output, " backend cycles idle "); 639a5d243d0SIngo Molnar } 640a5d243d0SIngo Molnar 641c78df6c1SIngo Molnar static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) 642c78df6c1SIngo Molnar { 643c78df6c1SIngo Molnar double total, ratio = 0.0; 644c78df6c1SIngo Molnar const char *color; 645c78df6c1SIngo Molnar 646c78df6c1SIngo Molnar total = avg_stats(&runtime_branches_stats[cpu]); 647c78df6c1SIngo Molnar 648c78df6c1SIngo Molnar if (total) 649c78df6c1SIngo Molnar ratio = avg / total * 100.0; 650c78df6c1SIngo Molnar 65115e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 652c78df6c1SIngo Molnar 6534aa9015fSStephane Eranian fprintf(output, " # "); 6544aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 6554aa9015fSStephane Eranian fprintf(output, " of all branches "); 656c78df6c1SIngo Molnar } 657c78df6c1SIngo Molnar 6588bb6c79fSIngo Molnar static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 6598bb6c79fSIngo Molnar { 6608bb6c79fSIngo Molnar double total, ratio = 0.0; 6618bb6c79fSIngo Molnar const char *color; 6628bb6c79fSIngo Molnar 6638bb6c79fSIngo Molnar total = avg_stats(&runtime_l1_dcache_stats[cpu]); 6648bb6c79fSIngo Molnar 6658bb6c79fSIngo Molnar if (total) 6668bb6c79fSIngo Molnar ratio = avg / total * 100.0; 6678bb6c79fSIngo Molnar 66815e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 6698bb6c79fSIngo Molnar 6704aa9015fSStephane Eranian fprintf(output, " # "); 6714aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 6724aa9015fSStephane Eranian fprintf(output, " of all L1-dcache hits "); 6738bb6c79fSIngo Molnar } 6748bb6c79fSIngo Molnar 675c3305257SIngo Molnar static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 676c3305257SIngo Molnar { 677c3305257SIngo Molnar double total, ratio = 0.0; 678c3305257SIngo Molnar const char *color; 679c3305257SIngo Molnar 680c3305257SIngo Molnar total = avg_stats(&runtime_l1_icache_stats[cpu]); 681c3305257SIngo Molnar 682c3305257SIngo Molnar if (total) 683c3305257SIngo Molnar ratio = avg / total * 100.0; 684c3305257SIngo Molnar 68515e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 686c3305257SIngo Molnar 6874aa9015fSStephane Eranian fprintf(output, " # "); 6884aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 6894aa9015fSStephane Eranian fprintf(output, " of all L1-icache hits "); 690c3305257SIngo Molnar } 691c3305257SIngo Molnar 692c3305257SIngo Molnar static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 693c3305257SIngo Molnar { 694c3305257SIngo Molnar double total, ratio = 0.0; 695c3305257SIngo Molnar const char *color; 696c3305257SIngo Molnar 697c3305257SIngo Molnar total = avg_stats(&runtime_dtlb_cache_stats[cpu]); 698c3305257SIngo Molnar 699c3305257SIngo Molnar if (total) 700c3305257SIngo Molnar ratio = avg / total * 100.0; 701c3305257SIngo Molnar 70215e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 703c3305257SIngo Molnar 7044aa9015fSStephane Eranian fprintf(output, " # "); 7054aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 7064aa9015fSStephane Eranian fprintf(output, " of all dTLB cache hits "); 707c3305257SIngo Molnar } 708c3305257SIngo Molnar 709c3305257SIngo Molnar static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 710c3305257SIngo Molnar { 711c3305257SIngo Molnar double total, ratio = 0.0; 712c3305257SIngo Molnar const char *color; 713c3305257SIngo Molnar 714c3305257SIngo Molnar total = avg_stats(&runtime_itlb_cache_stats[cpu]); 715c3305257SIngo Molnar 716c3305257SIngo Molnar if (total) 717c3305257SIngo Molnar ratio = avg / total * 100.0; 718c3305257SIngo Molnar 71915e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 720c3305257SIngo Molnar 7214aa9015fSStephane Eranian fprintf(output, " # "); 7224aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 7234aa9015fSStephane Eranian fprintf(output, " of all iTLB cache hits "); 724c3305257SIngo Molnar } 725c3305257SIngo Molnar 726c3305257SIngo Molnar static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 727c3305257SIngo Molnar { 728c3305257SIngo Molnar double total, ratio = 0.0; 729c3305257SIngo Molnar const char *color; 730c3305257SIngo Molnar 731c3305257SIngo Molnar total = avg_stats(&runtime_ll_cache_stats[cpu]); 732c3305257SIngo Molnar 733c3305257SIngo Molnar if (total) 734c3305257SIngo Molnar ratio = avg / total * 100.0; 735c3305257SIngo Molnar 73615e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 737c3305257SIngo Molnar 7384aa9015fSStephane Eranian fprintf(output, " # "); 7394aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 7404aa9015fSStephane Eranian fprintf(output, " of all LL-cache hits "); 741c3305257SIngo Molnar } 742c3305257SIngo Molnar 743daec78a0SArnaldo Carvalho de Melo static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) 74442202dd5SIngo Molnar { 745c7f7fea3SIngo Molnar double total, ratio = 0.0; 746f5b4a9c3SStephane Eranian char cpustr[16] = { '\0', }; 747d7470b6aSStephane Eranian const char *fmt; 748d7470b6aSStephane Eranian 749d7470b6aSStephane Eranian if (csv_output) 750d7470b6aSStephane Eranian fmt = "%s%.0f%s%s"; 751d7470b6aSStephane Eranian else if (big_num) 7522cba3ffbSIngo Molnar fmt = "%s%'18.0f%s%-25s"; 753d7470b6aSStephane Eranian else 7542cba3ffbSIngo Molnar fmt = "%s%18.0f%s%-25s"; 755f5b4a9c3SStephane Eranian 756f5b4a9c3SStephane Eranian if (no_aggr) 757d7470b6aSStephane Eranian sprintf(cpustr, "CPU%*d%s", 758d7470b6aSStephane Eranian csv_output ? 0 : -4, 7597e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep); 760f5b4a9c3SStephane Eranian else 761f5b4a9c3SStephane Eranian cpu = 0; 762c7f7fea3SIngo Molnar 7634aa9015fSStephane Eranian fprintf(output, fmt, cpustr, avg, csv_sep, event_name(evsel)); 764d7470b6aSStephane Eranian 765023695d9SStephane Eranian if (evsel->cgrp) 7664aa9015fSStephane Eranian fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 767023695d9SStephane Eranian 768d7470b6aSStephane Eranian if (csv_output) 769d7470b6aSStephane Eranian return; 77042202dd5SIngo Molnar 771daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 772f5b4a9c3SStephane Eranian total = avg_stats(&runtime_cycles_stats[cpu]); 773c7f7fea3SIngo Molnar 774c7f7fea3SIngo Molnar if (total) 775c7f7fea3SIngo Molnar ratio = avg / total; 776c7f7fea3SIngo Molnar 7774aa9015fSStephane Eranian fprintf(output, " # %5.2f insns per cycle ", ratio); 778481f988aSIngo Molnar 779d3d1e86dSIngo Molnar total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 780d3d1e86dSIngo Molnar total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 781481f988aSIngo Molnar 782481f988aSIngo Molnar if (total && avg) { 783481f988aSIngo Molnar ratio = total / avg; 7844aa9015fSStephane Eranian fprintf(output, "\n # %5.2f stalled cycles per insn", ratio); 785481f988aSIngo Molnar } 786481f988aSIngo Molnar 787daec78a0SArnaldo Carvalho de Melo } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && 788f5b4a9c3SStephane Eranian runtime_branches_stats[cpu].n != 0) { 789c78df6c1SIngo Molnar print_branch_misses(cpu, evsel, avg); 7908bb6c79fSIngo Molnar } else if ( 7918bb6c79fSIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 7928bb6c79fSIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | 7938bb6c79fSIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 7948bb6c79fSIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 795c6264defSIngo Molnar runtime_l1_dcache_stats[cpu].n != 0) { 7968bb6c79fSIngo Molnar print_l1_dcache_misses(cpu, evsel, avg); 797c3305257SIngo Molnar } else if ( 798c3305257SIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 799c3305257SIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I | 800c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 801c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 802c3305257SIngo Molnar runtime_l1_icache_stats[cpu].n != 0) { 803c3305257SIngo Molnar print_l1_icache_misses(cpu, evsel, avg); 804c3305257SIngo Molnar } else if ( 805c3305257SIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 806c3305257SIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB | 807c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 808c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 809c3305257SIngo Molnar runtime_dtlb_cache_stats[cpu].n != 0) { 810c3305257SIngo Molnar print_dtlb_cache_misses(cpu, evsel, avg); 811c3305257SIngo Molnar } else if ( 812c3305257SIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 813c3305257SIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB | 814c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 815c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 816c3305257SIngo Molnar runtime_itlb_cache_stats[cpu].n != 0) { 817c3305257SIngo Molnar print_itlb_cache_misses(cpu, evsel, avg); 818c3305257SIngo Molnar } else if ( 819c3305257SIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 820c3305257SIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL | 821c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 822c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 823c3305257SIngo Molnar runtime_ll_cache_stats[cpu].n != 0) { 824c3305257SIngo Molnar print_ll_cache_misses(cpu, evsel, avg); 825d58f4c82SIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) && 826d58f4c82SIngo Molnar runtime_cacherefs_stats[cpu].n != 0) { 827d58f4c82SIngo Molnar total = avg_stats(&runtime_cacherefs_stats[cpu]); 828d58f4c82SIngo Molnar 829d58f4c82SIngo Molnar if (total) 830d58f4c82SIngo Molnar ratio = avg * 100 / total; 831d58f4c82SIngo Molnar 8324aa9015fSStephane Eranian fprintf(output, " # %8.3f %% of all cache refs ", ratio); 833d58f4c82SIngo Molnar 834d3d1e86dSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { 835d3d1e86dSIngo Molnar print_stalled_cycles_frontend(cpu, evsel, avg); 836129c04cbSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) { 837d3d1e86dSIngo Molnar print_stalled_cycles_backend(cpu, evsel, avg); 838481f988aSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 839481f988aSIngo Molnar total = avg_stats(&runtime_nsecs_stats[cpu]); 840481f988aSIngo Molnar 841481f988aSIngo Molnar if (total) 842481f988aSIngo Molnar ratio = 1.0 * avg / total; 843481f988aSIngo Molnar 8444aa9015fSStephane Eranian fprintf(output, " # %8.3f GHz ", ratio); 845481f988aSIngo Molnar } else if (runtime_nsecs_stats[cpu].n != 0) { 8465fde2523SNamhyung Kim char unit = 'M'; 8475fde2523SNamhyung Kim 848481f988aSIngo Molnar total = avg_stats(&runtime_nsecs_stats[cpu]); 849481f988aSIngo Molnar 850481f988aSIngo Molnar if (total) 851481f988aSIngo Molnar ratio = 1000.0 * avg / total; 8525fde2523SNamhyung Kim if (ratio < 0.001) { 8535fde2523SNamhyung Kim ratio *= 1000; 8545fde2523SNamhyung Kim unit = 'K'; 8555fde2523SNamhyung Kim } 856481f988aSIngo Molnar 8575fde2523SNamhyung Kim fprintf(output, " # %8.3f %c/sec ", ratio, unit); 858a5d243d0SIngo Molnar } else { 8594aa9015fSStephane Eranian fprintf(output, " "); 86042202dd5SIngo Molnar } 86142202dd5SIngo Molnar } 86242202dd5SIngo Molnar 86342202dd5SIngo Molnar /* 86442202dd5SIngo Molnar * Print out the results of a single counter: 865f5b4a9c3SStephane Eranian * aggregated counts in system-wide mode 86642202dd5SIngo Molnar */ 86769aad6f1SArnaldo Carvalho de Melo static void print_counter_aggr(struct perf_evsel *counter) 86842202dd5SIngo Molnar { 86969aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps = counter->priv; 87069aad6f1SArnaldo Carvalho de Melo double avg = avg_stats(&ps->res_stats[0]); 871c52b12edSArnaldo Carvalho de Melo int scaled = counter->counts->scaled; 87242202dd5SIngo Molnar 87342202dd5SIngo Molnar if (scaled == -1) { 8744aa9015fSStephane Eranian fprintf(output, "%*s%s%*s", 875d7470b6aSStephane Eranian csv_output ? 0 : 18, 8762cee77c4SDavid Ahern counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 877023695d9SStephane Eranian csv_sep, 878023695d9SStephane Eranian csv_output ? 0 : -24, 879023695d9SStephane Eranian event_name(counter)); 880023695d9SStephane Eranian 881023695d9SStephane Eranian if (counter->cgrp) 8824aa9015fSStephane Eranian fprintf(output, "%s%s", csv_sep, counter->cgrp->name); 883023695d9SStephane Eranian 8844aa9015fSStephane Eranian fputc('\n', output); 88542202dd5SIngo Molnar return; 88642202dd5SIngo Molnar } 88742202dd5SIngo Molnar 88842202dd5SIngo Molnar if (nsec_counter(counter)) 889f5b4a9c3SStephane Eranian nsec_printout(-1, counter, avg); 89042202dd5SIngo Molnar else 891f5b4a9c3SStephane Eranian abs_printout(-1, counter, avg); 892849abde9SPeter Zijlstra 8933ae9a34dSZhengyu He print_noise(counter, avg); 8943ae9a34dSZhengyu He 895d7470b6aSStephane Eranian if (csv_output) { 8964aa9015fSStephane Eranian fputc('\n', output); 897d7470b6aSStephane Eranian return; 898d7470b6aSStephane Eranian } 899d7470b6aSStephane Eranian 900506d4bc8SPeter Zijlstra if (scaled) { 901506d4bc8SPeter Zijlstra double avg_enabled, avg_running; 902506d4bc8SPeter Zijlstra 90369aad6f1SArnaldo Carvalho de Melo avg_enabled = avg_stats(&ps->res_stats[1]); 90469aad6f1SArnaldo Carvalho de Melo avg_running = avg_stats(&ps->res_stats[2]); 905506d4bc8SPeter Zijlstra 9064aa9015fSStephane Eranian fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled); 907506d4bc8SPeter Zijlstra } 9084aa9015fSStephane Eranian fprintf(output, "\n"); 90942202dd5SIngo Molnar } 91042202dd5SIngo Molnar 911f5b4a9c3SStephane Eranian /* 912f5b4a9c3SStephane Eranian * Print out the results of a single counter: 913f5b4a9c3SStephane Eranian * does not use aggregated count in system-wide 914f5b4a9c3SStephane Eranian */ 91569aad6f1SArnaldo Carvalho de Melo static void print_counter(struct perf_evsel *counter) 916f5b4a9c3SStephane Eranian { 917f5b4a9c3SStephane Eranian u64 ena, run, val; 918f5b4a9c3SStephane Eranian int cpu; 919f5b4a9c3SStephane Eranian 9207e2ed097SArnaldo Carvalho de Melo for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 921c52b12edSArnaldo Carvalho de Melo val = counter->counts->cpu[cpu].val; 922c52b12edSArnaldo Carvalho de Melo ena = counter->counts->cpu[cpu].ena; 923c52b12edSArnaldo Carvalho de Melo run = counter->counts->cpu[cpu].run; 924f5b4a9c3SStephane Eranian if (run == 0 || ena == 0) { 9254aa9015fSStephane Eranian fprintf(output, "CPU%*d%s%*s%s%*s", 926d7470b6aSStephane Eranian csv_output ? 0 : -4, 9277e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep, 928d7470b6aSStephane Eranian csv_output ? 0 : 18, 9292cee77c4SDavid Ahern counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 9302cee77c4SDavid Ahern csv_sep, 931023695d9SStephane Eranian csv_output ? 0 : -24, 932d7470b6aSStephane Eranian event_name(counter)); 933f5b4a9c3SStephane Eranian 934023695d9SStephane Eranian if (counter->cgrp) 9354aa9015fSStephane Eranian fprintf(output, "%s%s", 9364aa9015fSStephane Eranian csv_sep, counter->cgrp->name); 937023695d9SStephane Eranian 9384aa9015fSStephane Eranian fputc('\n', output); 939f5b4a9c3SStephane Eranian continue; 940f5b4a9c3SStephane Eranian } 941f5b4a9c3SStephane Eranian 942f5b4a9c3SStephane Eranian if (nsec_counter(counter)) 943f5b4a9c3SStephane Eranian nsec_printout(cpu, counter, val); 944f5b4a9c3SStephane Eranian else 945f5b4a9c3SStephane Eranian abs_printout(cpu, counter, val); 946f5b4a9c3SStephane Eranian 947d7470b6aSStephane Eranian if (!csv_output) { 948f5b4a9c3SStephane Eranian print_noise(counter, 1.0); 949f5b4a9c3SStephane Eranian 950c6264defSIngo Molnar if (run != ena) 9514aa9015fSStephane Eranian fprintf(output, " (%.2f%%)", 9524aa9015fSStephane Eranian 100.0 * run / ena); 953d7470b6aSStephane Eranian } 9544aa9015fSStephane Eranian fputc('\n', output); 955f5b4a9c3SStephane Eranian } 956f5b4a9c3SStephane Eranian } 957f5b4a9c3SStephane Eranian 95842202dd5SIngo Molnar static void print_stat(int argc, const char **argv) 95942202dd5SIngo Molnar { 96069aad6f1SArnaldo Carvalho de Melo struct perf_evsel *counter; 96169aad6f1SArnaldo Carvalho de Melo int i; 96242202dd5SIngo Molnar 96386470930SIngo Molnar fflush(stdout); 96486470930SIngo Molnar 965d7470b6aSStephane Eranian if (!csv_output) { 9664aa9015fSStephane Eranian fprintf(output, "\n"); 9674aa9015fSStephane Eranian fprintf(output, " Performance counter stats for "); 968d67356e7SNamhyung Kim if (perf_target__no_task(&target)) { 9694aa9015fSStephane Eranian fprintf(output, "\'%s", argv[0]); 97086470930SIngo Molnar for (i = 1; i < argc; i++) 9714aa9015fSStephane Eranian fprintf(output, " %s", argv[i]); 97220f946b4SNamhyung Kim } else if (target.pid) 97320f946b4SNamhyung Kim fprintf(output, "process id \'%s", target.pid); 974d6d901c2SZhang, Yanmin else 97520f946b4SNamhyung Kim fprintf(output, "thread id \'%s", target.tid); 97686470930SIngo Molnar 9774aa9015fSStephane Eranian fprintf(output, "\'"); 97842202dd5SIngo Molnar if (run_count > 1) 9794aa9015fSStephane Eranian fprintf(output, " (%d runs)", run_count); 9804aa9015fSStephane Eranian fprintf(output, ":\n\n"); 981d7470b6aSStephane Eranian } 98286470930SIngo Molnar 983f5b4a9c3SStephane Eranian if (no_aggr) { 984361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) 98586470930SIngo Molnar print_counter(counter); 986f5b4a9c3SStephane Eranian } else { 987361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) 988f5b4a9c3SStephane Eranian print_counter_aggr(counter); 989f5b4a9c3SStephane Eranian } 99086470930SIngo Molnar 991d7470b6aSStephane Eranian if (!csv_output) { 992c3305257SIngo Molnar if (!null_run) 9934aa9015fSStephane Eranian fprintf(output, "\n"); 9944aa9015fSStephane Eranian fprintf(output, " %17.9f seconds time elapsed", 995506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)/1e9); 996566747e6SIngo Molnar if (run_count > 1) { 9974aa9015fSStephane Eranian fprintf(output, " "); 998f99844cbSIngo Molnar print_noise_pct(stddev_stats(&walltime_nsecs_stats), 999506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)); 1000566747e6SIngo Molnar } 10014aa9015fSStephane Eranian fprintf(output, "\n\n"); 100286470930SIngo Molnar } 1003d7470b6aSStephane Eranian } 100486470930SIngo Molnar 1005f7b7c26eSPeter Zijlstra static volatile int signr = -1; 1006f7b7c26eSPeter Zijlstra 100786470930SIngo Molnar static void skip_signal(int signo) 100886470930SIngo Molnar { 10096be2850eSZhang, Yanmin if(child_pid == -1) 101060666c63SLiming Wang done = 1; 101160666c63SLiming Wang 1012f7b7c26eSPeter Zijlstra signr = signo; 1013f7b7c26eSPeter Zijlstra } 1014f7b7c26eSPeter Zijlstra 1015f7b7c26eSPeter Zijlstra static void sig_atexit(void) 1016f7b7c26eSPeter Zijlstra { 1017933da83aSChris Wilson if (child_pid != -1) 1018933da83aSChris Wilson kill(child_pid, SIGTERM); 1019933da83aSChris Wilson 1020f7b7c26eSPeter Zijlstra if (signr == -1) 1021f7b7c26eSPeter Zijlstra return; 1022f7b7c26eSPeter Zijlstra 1023f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 1024f7b7c26eSPeter Zijlstra kill(getpid(), signr); 102586470930SIngo Molnar } 102686470930SIngo Molnar 102786470930SIngo Molnar static const char * const stat_usage[] = { 102860666c63SLiming Wang "perf stat [<options>] [<command>]", 102986470930SIngo Molnar NULL 103086470930SIngo Molnar }; 103186470930SIngo Molnar 1032d7470b6aSStephane Eranian static int stat__set_big_num(const struct option *opt __used, 1033d7470b6aSStephane Eranian const char *s __used, int unset) 1034d7470b6aSStephane Eranian { 1035d7470b6aSStephane Eranian big_num_opt = unset ? 0 : 1; 1036d7470b6aSStephane Eranian return 0; 1037d7470b6aSStephane Eranian } 1038d7470b6aSStephane Eranian 10394aa9015fSStephane Eranian static bool append_file; 10404aa9015fSStephane Eranian 104186470930SIngo Molnar static const struct option options[] = { 1042361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &evsel_list, "event", 104386470930SIngo Molnar "event selector. use 'perf list' to list available events", 1044f120f9d5SJiri Olsa parse_events_option), 1045cfd748aeSFrederic Weisbecker OPT_CALLBACK(0, "filter", &evsel_list, "filter", 1046cfd748aeSFrederic Weisbecker "event filter", parse_filter), 10472e6cdf99SStephane Eranian OPT_BOOLEAN('i', "no-inherit", &no_inherit, 10482e6cdf99SStephane Eranian "child tasks do not inherit counters"), 104920f946b4SNamhyung Kim OPT_STRING('p', "pid", &target.pid, "pid", 1050d6d901c2SZhang, Yanmin "stat events on existing process id"), 105120f946b4SNamhyung Kim OPT_STRING('t', "tid", &target.tid, "tid", 1052d6d901c2SZhang, Yanmin "stat events on existing thread id"), 105320f946b4SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &target.system_wide, 105486470930SIngo Molnar "system-wide collection from all CPUs"), 105543bece79SLin Ming OPT_BOOLEAN('g', "group", &group, 105643bece79SLin Ming "put the counters into a counter group"), 1057b26bc5a7SBrice Goglin OPT_BOOLEAN('c', "scale", &scale, 105886470930SIngo Molnar "scale/normalize counters"), 1059c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 1060743ee1f8SIngo Molnar "be more verbose (show counter open errors, etc)"), 106142202dd5SIngo Molnar OPT_INTEGER('r', "repeat", &run_count, 106242202dd5SIngo Molnar "repeat command and print average + stddev (max: 100)"), 10630cfb7a13SIngo Molnar OPT_BOOLEAN('n', "null", &null_run, 10640cfb7a13SIngo Molnar "null run - dont start any counters"), 10652cba3ffbSIngo Molnar OPT_INCR('d', "detailed", &detailed_run, 1066c6264defSIngo Molnar "detailed run - start a lot of events"), 1067f9cef0a9SIngo Molnar OPT_BOOLEAN('S', "sync", &sync_run, 1068f9cef0a9SIngo Molnar "call sync() before starting a run"), 1069d7470b6aSStephane Eranian OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 1070d7470b6aSStephane Eranian "print large numbers with thousands\' separators", 1071d7470b6aSStephane Eranian stat__set_big_num), 107220f946b4SNamhyung Kim OPT_STRING('C', "cpu", &target.cpu_list, "cpu", 1073c45c6ea2SStephane Eranian "list of cpus to monitor in system-wide"), 1074f5b4a9c3SStephane Eranian OPT_BOOLEAN('A', "no-aggr", &no_aggr, 1075f5b4a9c3SStephane Eranian "disable CPU count aggregation"), 1076d7470b6aSStephane Eranian OPT_STRING('x', "field-separator", &csv_sep, "separator", 1077d7470b6aSStephane Eranian "print counts with custom separator"), 1078023695d9SStephane Eranian OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 1079023695d9SStephane Eranian "monitor event in cgroup name only", 1080023695d9SStephane Eranian parse_cgroups), 10814aa9015fSStephane Eranian OPT_STRING('o', "output", &output_name, "file", 10824aa9015fSStephane Eranian "output file name"), 10834aa9015fSStephane Eranian OPT_BOOLEAN(0, "append", &append_file, "append to the output file"), 108456f3bae7SJim Cromie OPT_INTEGER(0, "log-fd", &output_fd, 108556f3bae7SJim Cromie "log output to fd, instead of stderr"), 108686470930SIngo Molnar OPT_END() 108786470930SIngo Molnar }; 108886470930SIngo Molnar 10892cba3ffbSIngo Molnar /* 10902cba3ffbSIngo Molnar * Add default attributes, if there were no attributes specified or 10912cba3ffbSIngo Molnar * if -d/--detailed, -d -d or -d -d -d is used: 10922cba3ffbSIngo Molnar */ 10932cba3ffbSIngo Molnar static int add_default_attributes(void) 10942cba3ffbSIngo Molnar { 10952cba3ffbSIngo Molnar /* Set attrs if no event is selected and !null_run: */ 10962cba3ffbSIngo Molnar if (null_run) 10972cba3ffbSIngo Molnar return 0; 10982cba3ffbSIngo Molnar 10992cba3ffbSIngo Molnar if (!evsel_list->nr_entries) { 110050d08e47SArnaldo Carvalho de Melo if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0) 11012cba3ffbSIngo Molnar return -1; 11022cba3ffbSIngo Molnar } 11032cba3ffbSIngo Molnar 11042cba3ffbSIngo Molnar /* Detailed events get appended to the event list: */ 11052cba3ffbSIngo Molnar 11062cba3ffbSIngo Molnar if (detailed_run < 1) 11072cba3ffbSIngo Molnar return 0; 11082cba3ffbSIngo Molnar 11092cba3ffbSIngo Molnar /* Append detailed run extra attributes: */ 111050d08e47SArnaldo Carvalho de Melo if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0) 11112cba3ffbSIngo Molnar return -1; 11122cba3ffbSIngo Molnar 11132cba3ffbSIngo Molnar if (detailed_run < 2) 11142cba3ffbSIngo Molnar return 0; 11152cba3ffbSIngo Molnar 11162cba3ffbSIngo Molnar /* Append very detailed run extra attributes: */ 111750d08e47SArnaldo Carvalho de Melo if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0) 11182cba3ffbSIngo Molnar return -1; 11192cba3ffbSIngo Molnar 11202cba3ffbSIngo Molnar if (detailed_run < 3) 11212cba3ffbSIngo Molnar return 0; 11222cba3ffbSIngo Molnar 11232cba3ffbSIngo Molnar /* Append very, very detailed run extra attributes: */ 112450d08e47SArnaldo Carvalho de Melo return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs); 11252cba3ffbSIngo Molnar } 11262cba3ffbSIngo Molnar 1127f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used) 112886470930SIngo Molnar { 112969aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 113069aad6f1SArnaldo Carvalho de Melo int status = -ENOMEM; 11314aa9015fSStephane Eranian const char *mode; 113242202dd5SIngo Molnar 11335af52b51SStephane Eranian setlocale(LC_ALL, ""); 11345af52b51SStephane Eranian 11357e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 1136361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 1137361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1138361c99a6SArnaldo Carvalho de Melo 1139a0541234SAnton Blanchard argc = parse_options(argc, argv, options, stat_usage, 1140a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1141d7470b6aSStephane Eranian 11424aa9015fSStephane Eranian output = stderr; 11434aa9015fSStephane Eranian if (output_name && strcmp(output_name, "-")) 11444aa9015fSStephane Eranian output = NULL; 11454aa9015fSStephane Eranian 114656f3bae7SJim Cromie if (output_name && output_fd) { 114756f3bae7SJim Cromie fprintf(stderr, "cannot use both --output and --log-fd\n"); 114856f3bae7SJim Cromie usage_with_options(stat_usage, options); 114956f3bae7SJim Cromie } 11504aa9015fSStephane Eranian if (!output) { 11514aa9015fSStephane Eranian struct timespec tm; 11524aa9015fSStephane Eranian mode = append_file ? "a" : "w"; 11534aa9015fSStephane Eranian 11544aa9015fSStephane Eranian output = fopen(output_name, mode); 11554aa9015fSStephane Eranian if (!output) { 11564aa9015fSStephane Eranian perror("failed to create output file"); 11574aa9015fSStephane Eranian exit(-1); 11584aa9015fSStephane Eranian } 11594aa9015fSStephane Eranian clock_gettime(CLOCK_REALTIME, &tm); 11604aa9015fSStephane Eranian fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); 116156f3bae7SJim Cromie } else if (output_fd != 2) { 116256f3bae7SJim Cromie mode = append_file ? "a" : "w"; 116356f3bae7SJim Cromie output = fdopen(output_fd, mode); 116456f3bae7SJim Cromie if (!output) { 116556f3bae7SJim Cromie perror("Failed opening logfd"); 116656f3bae7SJim Cromie return -errno; 116756f3bae7SJim Cromie } 11684aa9015fSStephane Eranian } 11694aa9015fSStephane Eranian 1170d4ffd04dSJim Cromie if (csv_sep) { 1171d7470b6aSStephane Eranian csv_output = true; 1172d4ffd04dSJim Cromie if (!strcmp(csv_sep, "\\t")) 1173d4ffd04dSJim Cromie csv_sep = "\t"; 1174d4ffd04dSJim Cromie } else 1175d7470b6aSStephane Eranian csv_sep = DEFAULT_SEPARATOR; 1176d7470b6aSStephane Eranian 1177d7470b6aSStephane Eranian /* 1178d7470b6aSStephane Eranian * let the spreadsheet do the pretty-printing 1179d7470b6aSStephane Eranian */ 1180d7470b6aSStephane Eranian if (csv_output) { 118161a9f324SJim Cromie /* User explicitly passed -B? */ 1182d7470b6aSStephane Eranian if (big_num_opt == 1) { 1183d7470b6aSStephane Eranian fprintf(stderr, "-B option not supported with -x\n"); 1184d7470b6aSStephane Eranian usage_with_options(stat_usage, options); 1185d7470b6aSStephane Eranian } else /* Nope, so disable big number formatting */ 1186d7470b6aSStephane Eranian big_num = false; 1187d7470b6aSStephane Eranian } else if (big_num_opt == 0) /* User passed --no-big-num */ 1188d7470b6aSStephane Eranian big_num = false; 1189d7470b6aSStephane Eranian 1190d67356e7SNamhyung Kim if (!argc && perf_target__no_task(&target)) 119186470930SIngo Molnar usage_with_options(stat_usage, options); 11929e9772c4SPeter Zijlstra if (run_count <= 0) 119342202dd5SIngo Molnar usage_with_options(stat_usage, options); 119486470930SIngo Molnar 1195023695d9SStephane Eranian /* no_aggr, cgroup are for system-wide only */ 1196d67356e7SNamhyung Kim if ((no_aggr || nr_cgroups) && perf_target__no_cpu(&target)) { 1197023695d9SStephane Eranian fprintf(stderr, "both cgroup and no-aggregation " 1198023695d9SStephane Eranian "modes only available in system-wide mode\n"); 1199023695d9SStephane Eranian 1200f5b4a9c3SStephane Eranian usage_with_options(stat_usage, options); 1201023695d9SStephane Eranian } 1202f5b4a9c3SStephane Eranian 12032cba3ffbSIngo Molnar if (add_default_attributes()) 1204c6264defSIngo Molnar goto out; 120586470930SIngo Molnar 12064bd0f2d2SNamhyung Kim perf_target__validate(&target); 12075c98d466SArnaldo Carvalho de Melo 120820f946b4SNamhyung Kim evsel_list->threads = thread_map__new_str(target.pid, 120920f946b4SNamhyung Kim target.tid, UINT_MAX); 12107e2ed097SArnaldo Carvalho de Melo if (evsel_list->threads == NULL) { 12115c98d466SArnaldo Carvalho de Melo pr_err("Problems finding threads of monitor\n"); 12125c98d466SArnaldo Carvalho de Melo usage_with_options(stat_usage, options); 12135c98d466SArnaldo Carvalho de Melo } 12145c98d466SArnaldo Carvalho de Melo 121520f946b4SNamhyung Kim if (target.system_wide) 121620f946b4SNamhyung Kim evsel_list->cpus = cpu_map__new(target.cpu_list); 1217a12b51c4SPaul Mackerras else 12187e2ed097SArnaldo Carvalho de Melo evsel_list->cpus = cpu_map__dummy_new(); 121986470930SIngo Molnar 12207e2ed097SArnaldo Carvalho de Melo if (evsel_list->cpus == NULL) { 122160d567e2SArnaldo Carvalho de Melo perror("failed to parse CPUs map"); 1222c45c6ea2SStephane Eranian usage_with_options(stat_usage, options); 122360d567e2SArnaldo Carvalho de Melo return -1; 122460d567e2SArnaldo Carvalho de Melo } 1225c45c6ea2SStephane Eranian 1226361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 1227c52b12edSArnaldo Carvalho de Melo if (perf_evsel__alloc_stat_priv(pos) < 0 || 1228806fb630SArnaldo Carvalho de Melo perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0) 122969aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 1230d6d901c2SZhang, Yanmin } 1231d6d901c2SZhang, Yanmin 123286470930SIngo Molnar /* 123386470930SIngo Molnar * We dont want to block the signals - that would cause 123486470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 123586470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 123686470930SIngo Molnar * task, but being ignored by perf stat itself: 123786470930SIngo Molnar */ 1238f7b7c26eSPeter Zijlstra atexit(sig_atexit); 123986470930SIngo Molnar signal(SIGINT, skip_signal); 124086470930SIngo Molnar signal(SIGALRM, skip_signal); 124186470930SIngo Molnar signal(SIGABRT, skip_signal); 124286470930SIngo Molnar 124342202dd5SIngo Molnar status = 0; 124442202dd5SIngo Molnar for (run_idx = 0; run_idx < run_count; run_idx++) { 124542202dd5SIngo Molnar if (run_count != 1 && verbose) 12464aa9015fSStephane Eranian fprintf(output, "[ perf stat: executing run #%d ... ]\n", 12474aa9015fSStephane Eranian run_idx + 1); 1248f9cef0a9SIngo Molnar 1249f9cef0a9SIngo Molnar if (sync_run) 1250f9cef0a9SIngo Molnar sync(); 1251f9cef0a9SIngo Molnar 125242202dd5SIngo Molnar status = run_perf_stat(argc, argv); 125342202dd5SIngo Molnar } 125442202dd5SIngo Molnar 1255084ab9f8SArnaldo Carvalho de Melo if (status != -1) 125642202dd5SIngo Molnar print_stat(argc, argv); 125769aad6f1SArnaldo Carvalho de Melo out_free_fd: 1258361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) 125969aad6f1SArnaldo Carvalho de Melo perf_evsel__free_stat_priv(pos); 12607e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 12610015e2e1SArnaldo Carvalho de Melo out: 12620015e2e1SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 126342202dd5SIngo Molnar return status; 126486470930SIngo Molnar } 1265