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 17877a6f014SNamhyung Kim static struct perf_target target = { 17977a6f014SNamhyung Kim .uid = UINT_MAX, 18077a6f014SNamhyung Kim }; 18142202dd5SIngo Molnar 18220f946b4SNamhyung Kim static int run_idx = 0; 1833d632595SJaswinder Singh Rajput static int run_count = 1; 1842e6cdf99SStephane Eranian static bool no_inherit = false; 185c0555642SIan Munsie static bool scale = true; 186f5b4a9c3SStephane Eranian static bool no_aggr = false; 187933da83aSChris Wilson static pid_t child_pid = -1; 188c0555642SIan Munsie static bool null_run = false; 1892cba3ffbSIngo Molnar static int detailed_run = 0; 190f9cef0a9SIngo Molnar static bool sync_run = false; 191201e0b06SArnaldo Carvalho de Melo static bool big_num = true; 192d7470b6aSStephane Eranian static int big_num_opt = -1; 193d7470b6aSStephane Eranian static const char *csv_sep = NULL; 194d7470b6aSStephane Eranian static bool csv_output = false; 19543bece79SLin Ming static bool group = false; 1964aa9015fSStephane Eranian static const char *output_name = NULL; 1974aa9015fSStephane Eranian static FILE *output = NULL; 19856f3bae7SJim Cromie static int output_fd; 1995af52b51SStephane Eranian 20060666c63SLiming Wang static volatile int done = 0; 20160666c63SLiming Wang 202506d4bc8SPeter Zijlstra struct stats 203506d4bc8SPeter Zijlstra { 2048a02631aSPeter Zijlstra double n, mean, M2; 205506d4bc8SPeter Zijlstra }; 20642202dd5SIngo Molnar 20769aad6f1SArnaldo Carvalho de Melo struct perf_stat { 20869aad6f1SArnaldo Carvalho de Melo struct stats res_stats[3]; 20969aad6f1SArnaldo Carvalho de Melo }; 21069aad6f1SArnaldo Carvalho de Melo 211c52b12edSArnaldo Carvalho de Melo static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) 21269aad6f1SArnaldo Carvalho de Melo { 213c52b12edSArnaldo Carvalho de Melo evsel->priv = zalloc(sizeof(struct perf_stat)); 21469aad6f1SArnaldo Carvalho de Melo return evsel->priv == NULL ? -ENOMEM : 0; 21569aad6f1SArnaldo Carvalho de Melo } 21669aad6f1SArnaldo Carvalho de Melo 21769aad6f1SArnaldo Carvalho de Melo static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 21869aad6f1SArnaldo Carvalho de Melo { 21969aad6f1SArnaldo Carvalho de Melo free(evsel->priv); 22069aad6f1SArnaldo Carvalho de Melo evsel->priv = NULL; 22169aad6f1SArnaldo Carvalho de Melo } 22269aad6f1SArnaldo Carvalho de Melo 2239e9772c4SPeter Zijlstra static void update_stats(struct stats *stats, u64 val) 2249e9772c4SPeter Zijlstra { 2258a02631aSPeter Zijlstra double delta; 2269e9772c4SPeter Zijlstra 2278a02631aSPeter Zijlstra stats->n++; 2288a02631aSPeter Zijlstra delta = val - stats->mean; 2298a02631aSPeter Zijlstra stats->mean += delta / stats->n; 2308a02631aSPeter Zijlstra stats->M2 += delta*(val - stats->mean); 2319e9772c4SPeter Zijlstra } 2329e9772c4SPeter Zijlstra 233506d4bc8SPeter Zijlstra static double avg_stats(struct stats *stats) 234506d4bc8SPeter Zijlstra { 2358a02631aSPeter Zijlstra return stats->mean; 236506d4bc8SPeter Zijlstra } 23742202dd5SIngo Molnar 238506d4bc8SPeter Zijlstra /* 23963d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance 24063d40debSPeter Zijlstra * 24163d40debSPeter Zijlstra * (\Sum n_i^2) - ((\Sum n_i)^2)/n 2428a02631aSPeter Zijlstra * s^2 = ------------------------------- 24363d40debSPeter Zijlstra * n - 1 24463d40debSPeter Zijlstra * 24563d40debSPeter Zijlstra * http://en.wikipedia.org/wiki/Stddev 24663d40debSPeter Zijlstra * 24763d40debSPeter Zijlstra * The std dev of the mean is related to the std dev by: 24863d40debSPeter Zijlstra * 24963d40debSPeter Zijlstra * s 25063d40debSPeter Zijlstra * s_mean = ------- 25163d40debSPeter Zijlstra * sqrt(n) 25263d40debSPeter Zijlstra * 253506d4bc8SPeter Zijlstra */ 254506d4bc8SPeter Zijlstra static double stddev_stats(struct stats *stats) 255506d4bc8SPeter Zijlstra { 25619f47402SJim Cromie double variance, variance_mean; 25719f47402SJim Cromie 25819f47402SJim Cromie if (!stats->n) 25919f47402SJim Cromie return 0.0; 26019f47402SJim Cromie 26119f47402SJim Cromie variance = stats->M2 / (stats->n - 1); 26219f47402SJim Cromie variance_mean = variance / stats->n; 26342202dd5SIngo Molnar 26463d40debSPeter Zijlstra return sqrt(variance_mean); 265506d4bc8SPeter Zijlstra } 26642202dd5SIngo Molnar 267666e6d48SRobert Richter static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; 268666e6d48SRobert Richter static struct stats runtime_cycles_stats[MAX_NR_CPUS]; 269666e6d48SRobert Richter static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS]; 270666e6d48SRobert Richter static struct stats runtime_stalled_cycles_back_stats[MAX_NR_CPUS]; 271666e6d48SRobert Richter static struct stats runtime_branches_stats[MAX_NR_CPUS]; 272666e6d48SRobert Richter static struct stats runtime_cacherefs_stats[MAX_NR_CPUS]; 273666e6d48SRobert Richter static struct stats runtime_l1_dcache_stats[MAX_NR_CPUS]; 274666e6d48SRobert Richter static struct stats runtime_l1_icache_stats[MAX_NR_CPUS]; 275666e6d48SRobert Richter static struct stats runtime_ll_cache_stats[MAX_NR_CPUS]; 276666e6d48SRobert Richter static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS]; 277666e6d48SRobert Richter static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; 278666e6d48SRobert Richter static struct stats walltime_nsecs_stats; 27986470930SIngo Molnar 280727ab04eSArnaldo Carvalho de Melo static int create_perf_stat_counter(struct perf_evsel *evsel, 281727ab04eSArnaldo Carvalho de Melo struct perf_evsel *first) 28286470930SIngo Molnar { 28369aad6f1SArnaldo Carvalho de Melo struct perf_event_attr *attr = &evsel->attr; 284727ab04eSArnaldo Carvalho de Melo struct xyarray *group_fd = NULL; 2855622c07bSStephane Eranian bool exclude_guest_missing = false; 2865622c07bSStephane Eranian int ret; 287727ab04eSArnaldo Carvalho de Melo 288727ab04eSArnaldo Carvalho de Melo if (group && evsel != first) 289727ab04eSArnaldo Carvalho de Melo group_fd = first->fd; 29086470930SIngo Molnar 29186470930SIngo Molnar if (scale) 29286470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 29386470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 29486470930SIngo Molnar 2952e6cdf99SStephane Eranian attr->inherit = !no_inherit; 2965d2cd909SArnaldo Carvalho de Melo 2975622c07bSStephane Eranian retry: 2985622c07bSStephane Eranian if (exclude_guest_missing) 2995622c07bSStephane Eranian evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; 3005622c07bSStephane Eranian 30116ee6576SArnaldo Carvalho de Melo if (perf_target__has_cpu(&target)) { 3025622c07bSStephane Eranian ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus, 303727ab04eSArnaldo Carvalho de Melo group, group_fd); 3045622c07bSStephane Eranian if (ret) 3055622c07bSStephane Eranian goto check_ret; 3065622c07bSStephane Eranian return 0; 3075622c07bSStephane Eranian } 3085622c07bSStephane Eranian 309aa22dd49SNamhyung Kim if (!perf_target__has_task(&target) && (!group || evsel == first)) { 31086470930SIngo Molnar attr->disabled = 1; 31157e7986eSPaul Mackerras attr->enable_on_exec = 1; 3126be2850eSZhang, Yanmin } 313084ab9f8SArnaldo Carvalho de Melo 3145622c07bSStephane Eranian ret = perf_evsel__open_per_thread(evsel, evsel_list->threads, 315727ab04eSArnaldo Carvalho de Melo group, group_fd); 3165622c07bSStephane Eranian if (!ret) 3175622c07bSStephane Eranian return 0; 3185622c07bSStephane Eranian /* fall through */ 3195622c07bSStephane Eranian check_ret: 3205622c07bSStephane Eranian if (ret && errno == EINVAL) { 3215622c07bSStephane Eranian if (!exclude_guest_missing && 3225622c07bSStephane Eranian (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { 3235622c07bSStephane Eranian pr_debug("Old kernel, cannot exclude " 3245622c07bSStephane Eranian "guest or host samples.\n"); 3255622c07bSStephane Eranian exclude_guest_missing = true; 3265622c07bSStephane Eranian goto retry; 3275622c07bSStephane Eranian } 3285622c07bSStephane Eranian } 3295622c07bSStephane Eranian return ret; 33086470930SIngo Molnar } 33186470930SIngo Molnar 33286470930SIngo Molnar /* 33386470930SIngo Molnar * Does the counter have nsecs as a unit? 33486470930SIngo Molnar */ 335daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel) 33686470930SIngo Molnar { 337daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) || 338daec78a0SArnaldo Carvalho de Melo perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 33986470930SIngo Molnar return 1; 34086470930SIngo Molnar 34186470930SIngo Molnar return 0; 34286470930SIngo Molnar } 34386470930SIngo Molnar 34486470930SIngo Molnar /* 345dcd9936aSIngo Molnar * Update various tracking values we maintain to print 346dcd9936aSIngo Molnar * more semantic information such as miss/hit ratios, 347dcd9936aSIngo Molnar * instruction rates, etc: 348dcd9936aSIngo Molnar */ 349dcd9936aSIngo Molnar static void update_shadow_stats(struct perf_evsel *counter, u64 *count) 350dcd9936aSIngo Molnar { 351dcd9936aSIngo Molnar if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 352dcd9936aSIngo Molnar update_stats(&runtime_nsecs_stats[0], count[0]); 353dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 354dcd9936aSIngo Molnar update_stats(&runtime_cycles_stats[0], count[0]); 355d3d1e86dSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 356d3d1e86dSIngo Molnar update_stats(&runtime_stalled_cycles_front_stats[0], count[0]); 357129c04cbSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 358d3d1e86dSIngo Molnar update_stats(&runtime_stalled_cycles_back_stats[0], count[0]); 359dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 360dcd9936aSIngo Molnar update_stats(&runtime_branches_stats[0], count[0]); 361dcd9936aSIngo Molnar else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 362dcd9936aSIngo Molnar update_stats(&runtime_cacherefs_stats[0], count[0]); 3638bb6c79fSIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) 3648bb6c79fSIngo Molnar update_stats(&runtime_l1_dcache_stats[0], count[0]); 365c3305257SIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) 366c3305257SIngo Molnar update_stats(&runtime_l1_icache_stats[0], count[0]); 367c3305257SIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) 368c3305257SIngo Molnar update_stats(&runtime_ll_cache_stats[0], count[0]); 369c3305257SIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) 370c3305257SIngo Molnar update_stats(&runtime_dtlb_cache_stats[0], count[0]); 371c3305257SIngo Molnar else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 372c3305257SIngo Molnar update_stats(&runtime_itlb_cache_stats[0], count[0]); 373dcd9936aSIngo Molnar } 374dcd9936aSIngo Molnar 375dcd9936aSIngo Molnar /* 37686470930SIngo Molnar * Read out the results of a single counter: 377f5b4a9c3SStephane Eranian * aggregate counts across CPUs in system-wide mode 37886470930SIngo Molnar */ 379c52b12edSArnaldo Carvalho de Melo static int read_counter_aggr(struct perf_evsel *counter) 38086470930SIngo Molnar { 38169aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps = counter->priv; 382c52b12edSArnaldo Carvalho de Melo u64 *count = counter->counts->aggr.values; 383c52b12edSArnaldo Carvalho de Melo int i; 38486470930SIngo Molnar 3857e2ed097SArnaldo Carvalho de Melo if (__perf_evsel__read(counter, evsel_list->cpus->nr, 3867e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr, scale) < 0) 387c52b12edSArnaldo Carvalho de Melo return -1; 3889e9772c4SPeter Zijlstra 3899e9772c4SPeter Zijlstra for (i = 0; i < 3; i++) 39069aad6f1SArnaldo Carvalho de Melo update_stats(&ps->res_stats[i], count[i]); 3919e9772c4SPeter Zijlstra 3929e9772c4SPeter Zijlstra if (verbose) { 3934aa9015fSStephane Eranian fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 3949486aa38SArnaldo Carvalho de Melo event_name(counter), count[0], count[1], count[2]); 3959e9772c4SPeter Zijlstra } 3969e9772c4SPeter Zijlstra 39786470930SIngo Molnar /* 39886470930SIngo Molnar * Save the full runtime - to allow normalization during printout: 39986470930SIngo Molnar */ 400dcd9936aSIngo Molnar update_shadow_stats(counter, count); 401c52b12edSArnaldo Carvalho de Melo 402c52b12edSArnaldo Carvalho de Melo return 0; 403f5b4a9c3SStephane Eranian } 404f5b4a9c3SStephane Eranian 405f5b4a9c3SStephane Eranian /* 406f5b4a9c3SStephane Eranian * Read out the results of a single counter: 407f5b4a9c3SStephane Eranian * do not aggregate counts across CPUs in system-wide mode 408f5b4a9c3SStephane Eranian */ 409c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter) 410f5b4a9c3SStephane Eranian { 411c52b12edSArnaldo Carvalho de Melo u64 *count; 412f5b4a9c3SStephane Eranian int cpu; 413f5b4a9c3SStephane Eranian 4147e2ed097SArnaldo Carvalho de Melo for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 415c52b12edSArnaldo Carvalho de Melo if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 416c52b12edSArnaldo Carvalho de Melo return -1; 417f5b4a9c3SStephane Eranian 418c52b12edSArnaldo Carvalho de Melo count = counter->counts->cpu[cpu].values; 419f5b4a9c3SStephane Eranian 420dcd9936aSIngo Molnar update_shadow_stats(counter, count); 421f5b4a9c3SStephane Eranian } 422c52b12edSArnaldo Carvalho de Melo 423c52b12edSArnaldo Carvalho de Melo return 0; 42486470930SIngo Molnar } 42586470930SIngo Molnar 426f37a291cSIngo Molnar static int run_perf_stat(int argc __used, const char **argv) 42786470930SIngo Molnar { 42886470930SIngo Molnar unsigned long long t0, t1; 429727ab04eSArnaldo Carvalho de Melo struct perf_evsel *counter, *first; 43042202dd5SIngo Molnar int status = 0; 431051ae7f7SPaul Mackerras int child_ready_pipe[2], go_pipe[2]; 4326be2850eSZhang, Yanmin const bool forks = (argc > 0); 433051ae7f7SPaul Mackerras char buf; 43486470930SIngo Molnar 43560666c63SLiming Wang if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 436051ae7f7SPaul Mackerras perror("failed to create pipes"); 437051ae7f7SPaul Mackerras exit(1); 438051ae7f7SPaul Mackerras } 439051ae7f7SPaul Mackerras 44060666c63SLiming Wang if (forks) { 4416be2850eSZhang, Yanmin if ((child_pid = fork()) < 0) 442051ae7f7SPaul Mackerras perror("failed to fork"); 443051ae7f7SPaul Mackerras 4446be2850eSZhang, Yanmin if (!child_pid) { 445051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 446051ae7f7SPaul Mackerras close(go_pipe[1]); 447051ae7f7SPaul Mackerras fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 448051ae7f7SPaul Mackerras 449051ae7f7SPaul Mackerras /* 450051ae7f7SPaul Mackerras * Do a dummy execvp to get the PLT entry resolved, 451051ae7f7SPaul Mackerras * so we avoid the resolver overhead on the real 452051ae7f7SPaul Mackerras * execvp call. 453051ae7f7SPaul Mackerras */ 454051ae7f7SPaul Mackerras execvp("", (char **)argv); 455051ae7f7SPaul Mackerras 456051ae7f7SPaul Mackerras /* 457051ae7f7SPaul Mackerras * Tell the parent we're ready to go 458051ae7f7SPaul Mackerras */ 459051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 460051ae7f7SPaul Mackerras 461051ae7f7SPaul Mackerras /* 462051ae7f7SPaul Mackerras * Wait until the parent tells us to go. 463051ae7f7SPaul Mackerras */ 464a92bef0fSFrederic Weisbecker if (read(go_pipe[0], &buf, 1) == -1) 465a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 466051ae7f7SPaul Mackerras 467051ae7f7SPaul Mackerras execvp(argv[0], (char **)argv); 468051ae7f7SPaul Mackerras 469051ae7f7SPaul Mackerras perror(argv[0]); 470051ae7f7SPaul Mackerras exit(-1); 471051ae7f7SPaul Mackerras } 472051ae7f7SPaul Mackerras 473d67356e7SNamhyung Kim if (perf_target__none(&target)) 4747e2ed097SArnaldo Carvalho de Melo evsel_list->threads->map[0] = child_pid; 475d6d901c2SZhang, Yanmin 476051ae7f7SPaul Mackerras /* 477051ae7f7SPaul Mackerras * Wait for the child to be ready to exec. 478051ae7f7SPaul Mackerras */ 479051ae7f7SPaul Mackerras close(child_ready_pipe[1]); 480051ae7f7SPaul Mackerras close(go_pipe[0]); 481a92bef0fSFrederic Weisbecker if (read(child_ready_pipe[0], &buf, 1) == -1) 482a92bef0fSFrederic Weisbecker perror("unable to read pipe"); 483051ae7f7SPaul Mackerras close(child_ready_pipe[0]); 48460666c63SLiming Wang } 485051ae7f7SPaul Mackerras 486727ab04eSArnaldo Carvalho de Melo first = list_entry(evsel_list->entries.next, struct perf_evsel, node); 487727ab04eSArnaldo Carvalho de Melo 488361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 489727ab04eSArnaldo Carvalho de Melo if (create_perf_stat_counter(counter, first) < 0) { 490979987a5SDavid Ahern /* 491979987a5SDavid Ahern * PPC returns ENXIO for HW counters until 2.6.37 492979987a5SDavid Ahern * (behavior changed with commit b0a873e). 493979987a5SDavid Ahern */ 49438f6ae1eSAnton Blanchard if (errno == EINVAL || errno == ENOSYS || 495979987a5SDavid Ahern errno == ENOENT || errno == EOPNOTSUPP || 496979987a5SDavid Ahern errno == ENXIO) { 497c63ca0c0SDavid Ahern if (verbose) 498c63ca0c0SDavid Ahern ui__warning("%s event is not supported by the kernel.\n", 499c63ca0c0SDavid Ahern event_name(counter)); 5002cee77c4SDavid Ahern counter->supported = false; 501ede70290SIngo Molnar continue; 502c63ca0c0SDavid Ahern } 503ede70290SIngo Molnar 504ede70290SIngo Molnar if (errno == EPERM || errno == EACCES) { 505d9cf837eSCorey Ashford error("You may not have permission to collect %sstats.\n" 506d9cf837eSCorey Ashford "\t Consider tweaking" 507d9cf837eSCorey Ashford " /proc/sys/kernel/perf_event_paranoid or running as root.", 50820f946b4SNamhyung Kim target.system_wide ? "system-wide " : ""); 50948290609SArnaldo Carvalho de Melo } else { 51048290609SArnaldo Carvalho de Melo error("open_counter returned with %d (%s). " 51148290609SArnaldo Carvalho de Melo "/bin/dmesg may provide additional information.\n", 51248290609SArnaldo Carvalho de Melo errno, strerror(errno)); 51348290609SArnaldo Carvalho de Melo } 514084ab9f8SArnaldo Carvalho de Melo if (child_pid != -1) 515084ab9f8SArnaldo Carvalho de Melo kill(child_pid, SIGTERM); 51648290609SArnaldo Carvalho de Melo die("Not all events could be opened.\n"); 517084ab9f8SArnaldo Carvalho de Melo return -1; 518084ab9f8SArnaldo Carvalho de Melo } 5192cee77c4SDavid Ahern counter->supported = true; 52048290609SArnaldo Carvalho de Melo } 52186470930SIngo Molnar 522cfd748aeSFrederic Weisbecker if (perf_evlist__set_filters(evsel_list)) { 523cfd748aeSFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 524cfd748aeSFrederic Weisbecker strerror(errno)); 525cfd748aeSFrederic Weisbecker return -1; 526cfd748aeSFrederic Weisbecker } 527cfd748aeSFrederic Weisbecker 52886470930SIngo Molnar /* 52986470930SIngo Molnar * Enable counters and exec the command: 53086470930SIngo Molnar */ 53186470930SIngo Molnar t0 = rdclock(); 53286470930SIngo Molnar 53360666c63SLiming Wang if (forks) { 534051ae7f7SPaul Mackerras close(go_pipe[1]); 53542202dd5SIngo Molnar wait(&status); 53633e49ea7SAndi Kleen if (WIFSIGNALED(status)) 53733e49ea7SAndi Kleen psignal(WTERMSIG(status), argv[0]); 53860666c63SLiming Wang } else { 5396be2850eSZhang, Yanmin while(!done) sleep(1); 54060666c63SLiming Wang } 54186470930SIngo Molnar 54286470930SIngo Molnar t1 = rdclock(); 54386470930SIngo Molnar 5449e9772c4SPeter Zijlstra update_stats(&walltime_nsecs_stats, t1 - t0); 54542202dd5SIngo Molnar 546f5b4a9c3SStephane Eranian if (no_aggr) { 547361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 54842202dd5SIngo Molnar read_counter(counter); 5497e2ed097SArnaldo Carvalho de Melo perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); 550f5b4a9c3SStephane Eranian } 551c52b12edSArnaldo Carvalho de Melo } else { 552361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) { 553c52b12edSArnaldo Carvalho de Melo read_counter_aggr(counter); 5547e2ed097SArnaldo Carvalho de Melo perf_evsel__close_fd(counter, evsel_list->cpus->nr, 5557e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr); 556c52b12edSArnaldo Carvalho de Melo } 557c52b12edSArnaldo Carvalho de Melo } 558c52b12edSArnaldo Carvalho de Melo 55942202dd5SIngo Molnar return WEXITSTATUS(status); 56042202dd5SIngo Molnar } 56142202dd5SIngo Molnar 562f99844cbSIngo Molnar static void print_noise_pct(double total, double avg) 563f99844cbSIngo Molnar { 564f99844cbSIngo Molnar double pct = 0.0; 565f99844cbSIngo Molnar 566f99844cbSIngo Molnar if (avg) 567f99844cbSIngo Molnar pct = 100.0*total/avg; 568f99844cbSIngo Molnar 5693ae9a34dSZhengyu He if (csv_output) 5704aa9015fSStephane Eranian fprintf(output, "%s%.2f%%", csv_sep, pct); 571a1bca6ccSJim Cromie else if (pct) 5724aa9015fSStephane Eranian fprintf(output, " ( +-%6.2f%% )", pct); 573f99844cbSIngo Molnar } 574f99844cbSIngo Molnar 57569aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg) 57642202dd5SIngo Molnar { 57769aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps; 57869aad6f1SArnaldo Carvalho de Melo 579849abde9SPeter Zijlstra if (run_count == 1) 580849abde9SPeter Zijlstra return; 581849abde9SPeter Zijlstra 58269aad6f1SArnaldo Carvalho de Melo ps = evsel->priv; 583f99844cbSIngo Molnar print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 58442202dd5SIngo Molnar } 58542202dd5SIngo Molnar 586daec78a0SArnaldo Carvalho de Melo static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) 58742202dd5SIngo Molnar { 588506d4bc8SPeter Zijlstra double msecs = avg / 1e6; 589d7470b6aSStephane Eranian char cpustr[16] = { '\0', }; 5902cba3ffbSIngo Molnar const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-25s"; 59142202dd5SIngo Molnar 592f5b4a9c3SStephane Eranian if (no_aggr) 593d7470b6aSStephane Eranian sprintf(cpustr, "CPU%*d%s", 594d7470b6aSStephane Eranian csv_output ? 0 : -4, 5957e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep); 596d7470b6aSStephane Eranian 5974aa9015fSStephane Eranian fprintf(output, fmt, cpustr, msecs, csv_sep, event_name(evsel)); 598d7470b6aSStephane Eranian 599023695d9SStephane Eranian if (evsel->cgrp) 6004aa9015fSStephane Eranian fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 601023695d9SStephane Eranian 602d7470b6aSStephane Eranian if (csv_output) 603d7470b6aSStephane Eranian return; 60442202dd5SIngo Molnar 605daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 6064aa9015fSStephane Eranian fprintf(output, " # %8.3f CPUs utilized ", 6074aa9015fSStephane Eranian avg / avg_stats(&walltime_nsecs_stats)); 6089dac6a29SNamhyung Kim else 6099dac6a29SNamhyung Kim fprintf(output, " "); 61042202dd5SIngo Molnar } 61142202dd5SIngo Molnar 61215e6392fSNamhyung Kim /* used for get_ratio_color() */ 61315e6392fSNamhyung Kim enum grc_type { 61415e6392fSNamhyung Kim GRC_STALLED_CYCLES_FE, 61515e6392fSNamhyung Kim GRC_STALLED_CYCLES_BE, 61615e6392fSNamhyung Kim GRC_CACHE_MISSES, 61715e6392fSNamhyung Kim GRC_MAX_NR 61815e6392fSNamhyung Kim }; 61915e6392fSNamhyung Kim 62015e6392fSNamhyung Kim static const char *get_ratio_color(enum grc_type type, double ratio) 62115e6392fSNamhyung Kim { 62215e6392fSNamhyung Kim static const double grc_table[GRC_MAX_NR][3] = { 62315e6392fSNamhyung Kim [GRC_STALLED_CYCLES_FE] = { 50.0, 30.0, 10.0 }, 62415e6392fSNamhyung Kim [GRC_STALLED_CYCLES_BE] = { 75.0, 50.0, 20.0 }, 62515e6392fSNamhyung Kim [GRC_CACHE_MISSES] = { 20.0, 10.0, 5.0 }, 62615e6392fSNamhyung Kim }; 62715e6392fSNamhyung Kim const char *color = PERF_COLOR_NORMAL; 62815e6392fSNamhyung Kim 62915e6392fSNamhyung Kim if (ratio > grc_table[type][0]) 63015e6392fSNamhyung Kim color = PERF_COLOR_RED; 63115e6392fSNamhyung Kim else if (ratio > grc_table[type][1]) 63215e6392fSNamhyung Kim color = PERF_COLOR_MAGENTA; 63315e6392fSNamhyung Kim else if (ratio > grc_table[type][2]) 63415e6392fSNamhyung Kim color = PERF_COLOR_YELLOW; 63515e6392fSNamhyung Kim 63615e6392fSNamhyung Kim return color; 63715e6392fSNamhyung Kim } 63815e6392fSNamhyung Kim 639d3d1e86dSIngo Molnar static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) 640d3d1e86dSIngo Molnar { 641d3d1e86dSIngo Molnar double total, ratio = 0.0; 642d3d1e86dSIngo Molnar const char *color; 643d3d1e86dSIngo Molnar 644d3d1e86dSIngo Molnar total = avg_stats(&runtime_cycles_stats[cpu]); 645d3d1e86dSIngo Molnar 646d3d1e86dSIngo Molnar if (total) 647d3d1e86dSIngo Molnar ratio = avg / total * 100.0; 648d3d1e86dSIngo Molnar 64915e6392fSNamhyung Kim color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio); 650d3d1e86dSIngo Molnar 6514aa9015fSStephane Eranian fprintf(output, " # "); 6524aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 6534aa9015fSStephane Eranian fprintf(output, " frontend cycles idle "); 654d3d1e86dSIngo Molnar } 655d3d1e86dSIngo Molnar 656d3d1e86dSIngo Molnar static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) 657a5d243d0SIngo Molnar { 658a5d243d0SIngo Molnar double total, ratio = 0.0; 659a5d243d0SIngo Molnar const char *color; 660a5d243d0SIngo Molnar 661a5d243d0SIngo Molnar total = avg_stats(&runtime_cycles_stats[cpu]); 662a5d243d0SIngo Molnar 663a5d243d0SIngo Molnar if (total) 664a5d243d0SIngo Molnar ratio = avg / total * 100.0; 665a5d243d0SIngo Molnar 66615e6392fSNamhyung Kim color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); 667a5d243d0SIngo Molnar 6684aa9015fSStephane Eranian fprintf(output, " # "); 6694aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 6704aa9015fSStephane Eranian fprintf(output, " backend cycles idle "); 671a5d243d0SIngo Molnar } 672a5d243d0SIngo Molnar 673c78df6c1SIngo Molnar static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) 674c78df6c1SIngo Molnar { 675c78df6c1SIngo Molnar double total, ratio = 0.0; 676c78df6c1SIngo Molnar const char *color; 677c78df6c1SIngo Molnar 678c78df6c1SIngo Molnar total = avg_stats(&runtime_branches_stats[cpu]); 679c78df6c1SIngo Molnar 680c78df6c1SIngo Molnar if (total) 681c78df6c1SIngo Molnar ratio = avg / total * 100.0; 682c78df6c1SIngo Molnar 68315e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 684c78df6c1SIngo Molnar 6854aa9015fSStephane Eranian fprintf(output, " # "); 6864aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 6874aa9015fSStephane Eranian fprintf(output, " of all branches "); 688c78df6c1SIngo Molnar } 689c78df6c1SIngo Molnar 6908bb6c79fSIngo Molnar static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 6918bb6c79fSIngo Molnar { 6928bb6c79fSIngo Molnar double total, ratio = 0.0; 6938bb6c79fSIngo Molnar const char *color; 6948bb6c79fSIngo Molnar 6958bb6c79fSIngo Molnar total = avg_stats(&runtime_l1_dcache_stats[cpu]); 6968bb6c79fSIngo Molnar 6978bb6c79fSIngo Molnar if (total) 6988bb6c79fSIngo Molnar ratio = avg / total * 100.0; 6998bb6c79fSIngo Molnar 70015e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 7018bb6c79fSIngo Molnar 7024aa9015fSStephane Eranian fprintf(output, " # "); 7034aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 7044aa9015fSStephane Eranian fprintf(output, " of all L1-dcache hits "); 7058bb6c79fSIngo Molnar } 7068bb6c79fSIngo Molnar 707c3305257SIngo Molnar static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 708c3305257SIngo Molnar { 709c3305257SIngo Molnar double total, ratio = 0.0; 710c3305257SIngo Molnar const char *color; 711c3305257SIngo Molnar 712c3305257SIngo Molnar total = avg_stats(&runtime_l1_icache_stats[cpu]); 713c3305257SIngo Molnar 714c3305257SIngo Molnar if (total) 715c3305257SIngo Molnar ratio = avg / total * 100.0; 716c3305257SIngo Molnar 71715e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 718c3305257SIngo Molnar 7194aa9015fSStephane Eranian fprintf(output, " # "); 7204aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 7214aa9015fSStephane Eranian fprintf(output, " of all L1-icache hits "); 722c3305257SIngo Molnar } 723c3305257SIngo Molnar 724c3305257SIngo Molnar static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 725c3305257SIngo Molnar { 726c3305257SIngo Molnar double total, ratio = 0.0; 727c3305257SIngo Molnar const char *color; 728c3305257SIngo Molnar 729c3305257SIngo Molnar total = avg_stats(&runtime_dtlb_cache_stats[cpu]); 730c3305257SIngo Molnar 731c3305257SIngo Molnar if (total) 732c3305257SIngo Molnar ratio = avg / total * 100.0; 733c3305257SIngo Molnar 73415e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 735c3305257SIngo Molnar 7364aa9015fSStephane Eranian fprintf(output, " # "); 7374aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 7384aa9015fSStephane Eranian fprintf(output, " of all dTLB cache hits "); 739c3305257SIngo Molnar } 740c3305257SIngo Molnar 741c3305257SIngo Molnar static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 742c3305257SIngo Molnar { 743c3305257SIngo Molnar double total, ratio = 0.0; 744c3305257SIngo Molnar const char *color; 745c3305257SIngo Molnar 746c3305257SIngo Molnar total = avg_stats(&runtime_itlb_cache_stats[cpu]); 747c3305257SIngo Molnar 748c3305257SIngo Molnar if (total) 749c3305257SIngo Molnar ratio = avg / total * 100.0; 750c3305257SIngo Molnar 75115e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 752c3305257SIngo Molnar 7534aa9015fSStephane Eranian fprintf(output, " # "); 7544aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 7554aa9015fSStephane Eranian fprintf(output, " of all iTLB cache hits "); 756c3305257SIngo Molnar } 757c3305257SIngo Molnar 758c3305257SIngo Molnar static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) 759c3305257SIngo Molnar { 760c3305257SIngo Molnar double total, ratio = 0.0; 761c3305257SIngo Molnar const char *color; 762c3305257SIngo Molnar 763c3305257SIngo Molnar total = avg_stats(&runtime_ll_cache_stats[cpu]); 764c3305257SIngo Molnar 765c3305257SIngo Molnar if (total) 766c3305257SIngo Molnar ratio = avg / total * 100.0; 767c3305257SIngo Molnar 76815e6392fSNamhyung Kim color = get_ratio_color(GRC_CACHE_MISSES, ratio); 769c3305257SIngo Molnar 7704aa9015fSStephane Eranian fprintf(output, " # "); 7714aa9015fSStephane Eranian color_fprintf(output, color, "%6.2f%%", ratio); 7724aa9015fSStephane Eranian fprintf(output, " of all LL-cache hits "); 773c3305257SIngo Molnar } 774c3305257SIngo Molnar 775daec78a0SArnaldo Carvalho de Melo static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) 77642202dd5SIngo Molnar { 777c7f7fea3SIngo Molnar double total, ratio = 0.0; 778f5b4a9c3SStephane Eranian char cpustr[16] = { '\0', }; 779d7470b6aSStephane Eranian const char *fmt; 780d7470b6aSStephane Eranian 781d7470b6aSStephane Eranian if (csv_output) 782d7470b6aSStephane Eranian fmt = "%s%.0f%s%s"; 783d7470b6aSStephane Eranian else if (big_num) 7842cba3ffbSIngo Molnar fmt = "%s%'18.0f%s%-25s"; 785d7470b6aSStephane Eranian else 7862cba3ffbSIngo Molnar fmt = "%s%18.0f%s%-25s"; 787f5b4a9c3SStephane Eranian 788f5b4a9c3SStephane Eranian if (no_aggr) 789d7470b6aSStephane Eranian sprintf(cpustr, "CPU%*d%s", 790d7470b6aSStephane Eranian csv_output ? 0 : -4, 7917e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep); 792f5b4a9c3SStephane Eranian else 793f5b4a9c3SStephane Eranian cpu = 0; 794c7f7fea3SIngo Molnar 7954aa9015fSStephane Eranian fprintf(output, fmt, cpustr, avg, csv_sep, event_name(evsel)); 796d7470b6aSStephane Eranian 797023695d9SStephane Eranian if (evsel->cgrp) 7984aa9015fSStephane Eranian fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 799023695d9SStephane Eranian 800d7470b6aSStephane Eranian if (csv_output) 801d7470b6aSStephane Eranian return; 80242202dd5SIngo Molnar 803daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 804f5b4a9c3SStephane Eranian total = avg_stats(&runtime_cycles_stats[cpu]); 805c7f7fea3SIngo Molnar 806c7f7fea3SIngo Molnar if (total) 807c7f7fea3SIngo Molnar ratio = avg / total; 808c7f7fea3SIngo Molnar 8094aa9015fSStephane Eranian fprintf(output, " # %5.2f insns per cycle ", ratio); 810481f988aSIngo Molnar 811d3d1e86dSIngo Molnar total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 812d3d1e86dSIngo Molnar total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 813481f988aSIngo Molnar 814481f988aSIngo Molnar if (total && avg) { 815481f988aSIngo Molnar ratio = total / avg; 8164aa9015fSStephane Eranian fprintf(output, "\n # %5.2f stalled cycles per insn", ratio); 817481f988aSIngo Molnar } 818481f988aSIngo Molnar 819daec78a0SArnaldo Carvalho de Melo } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && 820f5b4a9c3SStephane Eranian runtime_branches_stats[cpu].n != 0) { 821c78df6c1SIngo Molnar print_branch_misses(cpu, evsel, avg); 8228bb6c79fSIngo Molnar } else if ( 8238bb6c79fSIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 8248bb6c79fSIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | 8258bb6c79fSIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 8268bb6c79fSIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 827c6264defSIngo Molnar runtime_l1_dcache_stats[cpu].n != 0) { 8288bb6c79fSIngo Molnar print_l1_dcache_misses(cpu, evsel, avg); 829c3305257SIngo Molnar } else if ( 830c3305257SIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 831c3305257SIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I | 832c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 833c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 834c3305257SIngo Molnar runtime_l1_icache_stats[cpu].n != 0) { 835c3305257SIngo Molnar print_l1_icache_misses(cpu, evsel, avg); 836c3305257SIngo Molnar } else if ( 837c3305257SIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 838c3305257SIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB | 839c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 840c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 841c3305257SIngo Molnar runtime_dtlb_cache_stats[cpu].n != 0) { 842c3305257SIngo Molnar print_dtlb_cache_misses(cpu, evsel, avg); 843c3305257SIngo Molnar } else if ( 844c3305257SIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 845c3305257SIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB | 846c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 847c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 848c3305257SIngo Molnar runtime_itlb_cache_stats[cpu].n != 0) { 849c3305257SIngo Molnar print_itlb_cache_misses(cpu, evsel, avg); 850c3305257SIngo Molnar } else if ( 851c3305257SIngo Molnar evsel->attr.type == PERF_TYPE_HW_CACHE && 852c3305257SIngo Molnar evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL | 853c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_OP_READ) << 8) | 854c3305257SIngo Molnar ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) && 855c3305257SIngo Molnar runtime_ll_cache_stats[cpu].n != 0) { 856c3305257SIngo Molnar print_ll_cache_misses(cpu, evsel, avg); 857d58f4c82SIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) && 858d58f4c82SIngo Molnar runtime_cacherefs_stats[cpu].n != 0) { 859d58f4c82SIngo Molnar total = avg_stats(&runtime_cacherefs_stats[cpu]); 860d58f4c82SIngo Molnar 861d58f4c82SIngo Molnar if (total) 862d58f4c82SIngo Molnar ratio = avg * 100 / total; 863d58f4c82SIngo Molnar 8644aa9015fSStephane Eranian fprintf(output, " # %8.3f %% of all cache refs ", ratio); 865d58f4c82SIngo Molnar 866d3d1e86dSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { 867d3d1e86dSIngo Molnar print_stalled_cycles_frontend(cpu, evsel, avg); 868129c04cbSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) { 869d3d1e86dSIngo Molnar print_stalled_cycles_backend(cpu, evsel, avg); 870481f988aSIngo Molnar } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 871481f988aSIngo Molnar total = avg_stats(&runtime_nsecs_stats[cpu]); 872481f988aSIngo Molnar 873481f988aSIngo Molnar if (total) 874481f988aSIngo Molnar ratio = 1.0 * avg / total; 875481f988aSIngo Molnar 8764aa9015fSStephane Eranian fprintf(output, " # %8.3f GHz ", ratio); 877481f988aSIngo Molnar } else if (runtime_nsecs_stats[cpu].n != 0) { 8785fde2523SNamhyung Kim char unit = 'M'; 8795fde2523SNamhyung Kim 880481f988aSIngo Molnar total = avg_stats(&runtime_nsecs_stats[cpu]); 881481f988aSIngo Molnar 882481f988aSIngo Molnar if (total) 883481f988aSIngo Molnar ratio = 1000.0 * avg / total; 8845fde2523SNamhyung Kim if (ratio < 0.001) { 8855fde2523SNamhyung Kim ratio *= 1000; 8865fde2523SNamhyung Kim unit = 'K'; 8875fde2523SNamhyung Kim } 888481f988aSIngo Molnar 8895fde2523SNamhyung Kim fprintf(output, " # %8.3f %c/sec ", ratio, unit); 890a5d243d0SIngo Molnar } else { 8914aa9015fSStephane Eranian fprintf(output, " "); 89242202dd5SIngo Molnar } 89342202dd5SIngo Molnar } 89442202dd5SIngo Molnar 89542202dd5SIngo Molnar /* 89642202dd5SIngo Molnar * Print out the results of a single counter: 897f5b4a9c3SStephane Eranian * aggregated counts in system-wide mode 89842202dd5SIngo Molnar */ 89969aad6f1SArnaldo Carvalho de Melo static void print_counter_aggr(struct perf_evsel *counter) 90042202dd5SIngo Molnar { 90169aad6f1SArnaldo Carvalho de Melo struct perf_stat *ps = counter->priv; 90269aad6f1SArnaldo Carvalho de Melo double avg = avg_stats(&ps->res_stats[0]); 903c52b12edSArnaldo Carvalho de Melo int scaled = counter->counts->scaled; 90442202dd5SIngo Molnar 90542202dd5SIngo Molnar if (scaled == -1) { 9064aa9015fSStephane Eranian fprintf(output, "%*s%s%*s", 907d7470b6aSStephane Eranian csv_output ? 0 : 18, 9082cee77c4SDavid Ahern counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 909023695d9SStephane Eranian csv_sep, 910023695d9SStephane Eranian csv_output ? 0 : -24, 911023695d9SStephane Eranian event_name(counter)); 912023695d9SStephane Eranian 913023695d9SStephane Eranian if (counter->cgrp) 9144aa9015fSStephane Eranian fprintf(output, "%s%s", csv_sep, counter->cgrp->name); 915023695d9SStephane Eranian 9164aa9015fSStephane Eranian fputc('\n', output); 91742202dd5SIngo Molnar return; 91842202dd5SIngo Molnar } 91942202dd5SIngo Molnar 92042202dd5SIngo Molnar if (nsec_counter(counter)) 921f5b4a9c3SStephane Eranian nsec_printout(-1, counter, avg); 92242202dd5SIngo Molnar else 923f5b4a9c3SStephane Eranian abs_printout(-1, counter, avg); 924849abde9SPeter Zijlstra 9253ae9a34dSZhengyu He print_noise(counter, avg); 9263ae9a34dSZhengyu He 927d7470b6aSStephane Eranian if (csv_output) { 9284aa9015fSStephane Eranian fputc('\n', output); 929d7470b6aSStephane Eranian return; 930d7470b6aSStephane Eranian } 931d7470b6aSStephane Eranian 932506d4bc8SPeter Zijlstra if (scaled) { 933506d4bc8SPeter Zijlstra double avg_enabled, avg_running; 934506d4bc8SPeter Zijlstra 93569aad6f1SArnaldo Carvalho de Melo avg_enabled = avg_stats(&ps->res_stats[1]); 93669aad6f1SArnaldo Carvalho de Melo avg_running = avg_stats(&ps->res_stats[2]); 937506d4bc8SPeter Zijlstra 9384aa9015fSStephane Eranian fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled); 939506d4bc8SPeter Zijlstra } 9404aa9015fSStephane Eranian fprintf(output, "\n"); 94142202dd5SIngo Molnar } 94242202dd5SIngo Molnar 943f5b4a9c3SStephane Eranian /* 944f5b4a9c3SStephane Eranian * Print out the results of a single counter: 945f5b4a9c3SStephane Eranian * does not use aggregated count in system-wide 946f5b4a9c3SStephane Eranian */ 94769aad6f1SArnaldo Carvalho de Melo static void print_counter(struct perf_evsel *counter) 948f5b4a9c3SStephane Eranian { 949f5b4a9c3SStephane Eranian u64 ena, run, val; 950f5b4a9c3SStephane Eranian int cpu; 951f5b4a9c3SStephane Eranian 9527e2ed097SArnaldo Carvalho de Melo for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { 953c52b12edSArnaldo Carvalho de Melo val = counter->counts->cpu[cpu].val; 954c52b12edSArnaldo Carvalho de Melo ena = counter->counts->cpu[cpu].ena; 955c52b12edSArnaldo Carvalho de Melo run = counter->counts->cpu[cpu].run; 956f5b4a9c3SStephane Eranian if (run == 0 || ena == 0) { 9574aa9015fSStephane Eranian fprintf(output, "CPU%*d%s%*s%s%*s", 958d7470b6aSStephane Eranian csv_output ? 0 : -4, 9597e2ed097SArnaldo Carvalho de Melo evsel_list->cpus->map[cpu], csv_sep, 960d7470b6aSStephane Eranian csv_output ? 0 : 18, 9612cee77c4SDavid Ahern counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 9622cee77c4SDavid Ahern csv_sep, 963023695d9SStephane Eranian csv_output ? 0 : -24, 964d7470b6aSStephane Eranian event_name(counter)); 965f5b4a9c3SStephane Eranian 966023695d9SStephane Eranian if (counter->cgrp) 9674aa9015fSStephane Eranian fprintf(output, "%s%s", 9684aa9015fSStephane Eranian csv_sep, counter->cgrp->name); 969023695d9SStephane Eranian 9704aa9015fSStephane Eranian fputc('\n', output); 971f5b4a9c3SStephane Eranian continue; 972f5b4a9c3SStephane Eranian } 973f5b4a9c3SStephane Eranian 974f5b4a9c3SStephane Eranian if (nsec_counter(counter)) 975f5b4a9c3SStephane Eranian nsec_printout(cpu, counter, val); 976f5b4a9c3SStephane Eranian else 977f5b4a9c3SStephane Eranian abs_printout(cpu, counter, val); 978f5b4a9c3SStephane Eranian 979d7470b6aSStephane Eranian if (!csv_output) { 980f5b4a9c3SStephane Eranian print_noise(counter, 1.0); 981f5b4a9c3SStephane Eranian 982c6264defSIngo Molnar if (run != ena) 9834aa9015fSStephane Eranian fprintf(output, " (%.2f%%)", 9844aa9015fSStephane Eranian 100.0 * run / ena); 985d7470b6aSStephane Eranian } 9864aa9015fSStephane Eranian fputc('\n', output); 987f5b4a9c3SStephane Eranian } 988f5b4a9c3SStephane Eranian } 989f5b4a9c3SStephane Eranian 99042202dd5SIngo Molnar static void print_stat(int argc, const char **argv) 99142202dd5SIngo Molnar { 99269aad6f1SArnaldo Carvalho de Melo struct perf_evsel *counter; 99369aad6f1SArnaldo Carvalho de Melo int i; 99442202dd5SIngo Molnar 99586470930SIngo Molnar fflush(stdout); 99686470930SIngo Molnar 997d7470b6aSStephane Eranian if (!csv_output) { 9984aa9015fSStephane Eranian fprintf(output, "\n"); 9994aa9015fSStephane Eranian fprintf(output, " Performance counter stats for "); 1000aa22dd49SNamhyung Kim if (!perf_target__has_task(&target)) { 10014aa9015fSStephane Eranian fprintf(output, "\'%s", argv[0]); 100286470930SIngo Molnar for (i = 1; i < argc; i++) 10034aa9015fSStephane Eranian fprintf(output, " %s", argv[i]); 100420f946b4SNamhyung Kim } else if (target.pid) 100520f946b4SNamhyung Kim fprintf(output, "process id \'%s", target.pid); 1006d6d901c2SZhang, Yanmin else 100720f946b4SNamhyung Kim fprintf(output, "thread id \'%s", target.tid); 100886470930SIngo Molnar 10094aa9015fSStephane Eranian fprintf(output, "\'"); 101042202dd5SIngo Molnar if (run_count > 1) 10114aa9015fSStephane Eranian fprintf(output, " (%d runs)", run_count); 10124aa9015fSStephane Eranian fprintf(output, ":\n\n"); 1013d7470b6aSStephane Eranian } 101486470930SIngo Molnar 1015f5b4a9c3SStephane Eranian if (no_aggr) { 1016361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) 101786470930SIngo Molnar print_counter(counter); 1018f5b4a9c3SStephane Eranian } else { 1019361c99a6SArnaldo Carvalho de Melo list_for_each_entry(counter, &evsel_list->entries, node) 1020f5b4a9c3SStephane Eranian print_counter_aggr(counter); 1021f5b4a9c3SStephane Eranian } 102286470930SIngo Molnar 1023d7470b6aSStephane Eranian if (!csv_output) { 1024c3305257SIngo Molnar if (!null_run) 10254aa9015fSStephane Eranian fprintf(output, "\n"); 10264aa9015fSStephane Eranian fprintf(output, " %17.9f seconds time elapsed", 1027506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)/1e9); 1028566747e6SIngo Molnar if (run_count > 1) { 10294aa9015fSStephane Eranian fprintf(output, " "); 1030f99844cbSIngo Molnar print_noise_pct(stddev_stats(&walltime_nsecs_stats), 1031506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)); 1032566747e6SIngo Molnar } 10334aa9015fSStephane Eranian fprintf(output, "\n\n"); 103486470930SIngo Molnar } 1035d7470b6aSStephane Eranian } 103686470930SIngo Molnar 1037f7b7c26eSPeter Zijlstra static volatile int signr = -1; 1038f7b7c26eSPeter Zijlstra 103986470930SIngo Molnar static void skip_signal(int signo) 104086470930SIngo Molnar { 10416be2850eSZhang, Yanmin if(child_pid == -1) 104260666c63SLiming Wang done = 1; 104360666c63SLiming Wang 1044f7b7c26eSPeter Zijlstra signr = signo; 1045f7b7c26eSPeter Zijlstra } 1046f7b7c26eSPeter Zijlstra 1047f7b7c26eSPeter Zijlstra static void sig_atexit(void) 1048f7b7c26eSPeter Zijlstra { 1049933da83aSChris Wilson if (child_pid != -1) 1050933da83aSChris Wilson kill(child_pid, SIGTERM); 1051933da83aSChris Wilson 1052f7b7c26eSPeter Zijlstra if (signr == -1) 1053f7b7c26eSPeter Zijlstra return; 1054f7b7c26eSPeter Zijlstra 1055f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 1056f7b7c26eSPeter Zijlstra kill(getpid(), signr); 105786470930SIngo Molnar } 105886470930SIngo Molnar 105986470930SIngo Molnar static const char * const stat_usage[] = { 106060666c63SLiming Wang "perf stat [<options>] [<command>]", 106186470930SIngo Molnar NULL 106286470930SIngo Molnar }; 106386470930SIngo Molnar 1064d7470b6aSStephane Eranian static int stat__set_big_num(const struct option *opt __used, 1065d7470b6aSStephane Eranian const char *s __used, int unset) 1066d7470b6aSStephane Eranian { 1067d7470b6aSStephane Eranian big_num_opt = unset ? 0 : 1; 1068d7470b6aSStephane Eranian return 0; 1069d7470b6aSStephane Eranian } 1070d7470b6aSStephane Eranian 10714aa9015fSStephane Eranian static bool append_file; 10724aa9015fSStephane Eranian 107386470930SIngo Molnar static const struct option options[] = { 1074361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &evsel_list, "event", 107586470930SIngo Molnar "event selector. use 'perf list' to list available events", 1076f120f9d5SJiri Olsa parse_events_option), 1077cfd748aeSFrederic Weisbecker OPT_CALLBACK(0, "filter", &evsel_list, "filter", 1078cfd748aeSFrederic Weisbecker "event filter", parse_filter), 10792e6cdf99SStephane Eranian OPT_BOOLEAN('i', "no-inherit", &no_inherit, 10802e6cdf99SStephane Eranian "child tasks do not inherit counters"), 108120f946b4SNamhyung Kim OPT_STRING('p', "pid", &target.pid, "pid", 1082d6d901c2SZhang, Yanmin "stat events on existing process id"), 108320f946b4SNamhyung Kim OPT_STRING('t', "tid", &target.tid, "tid", 1084d6d901c2SZhang, Yanmin "stat events on existing thread id"), 108520f946b4SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &target.system_wide, 108686470930SIngo Molnar "system-wide collection from all CPUs"), 108743bece79SLin Ming OPT_BOOLEAN('g', "group", &group, 108843bece79SLin Ming "put the counters into a counter group"), 1089b26bc5a7SBrice Goglin OPT_BOOLEAN('c', "scale", &scale, 109086470930SIngo Molnar "scale/normalize counters"), 1091c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 1092743ee1f8SIngo Molnar "be more verbose (show counter open errors, etc)"), 109342202dd5SIngo Molnar OPT_INTEGER('r', "repeat", &run_count, 109442202dd5SIngo Molnar "repeat command and print average + stddev (max: 100)"), 10950cfb7a13SIngo Molnar OPT_BOOLEAN('n', "null", &null_run, 10960cfb7a13SIngo Molnar "null run - dont start any counters"), 10972cba3ffbSIngo Molnar OPT_INCR('d', "detailed", &detailed_run, 1098c6264defSIngo Molnar "detailed run - start a lot of events"), 1099f9cef0a9SIngo Molnar OPT_BOOLEAN('S', "sync", &sync_run, 1100f9cef0a9SIngo Molnar "call sync() before starting a run"), 1101d7470b6aSStephane Eranian OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 1102d7470b6aSStephane Eranian "print large numbers with thousands\' separators", 1103d7470b6aSStephane Eranian stat__set_big_num), 110420f946b4SNamhyung Kim OPT_STRING('C', "cpu", &target.cpu_list, "cpu", 1105c45c6ea2SStephane Eranian "list of cpus to monitor in system-wide"), 1106f5b4a9c3SStephane Eranian OPT_BOOLEAN('A', "no-aggr", &no_aggr, 1107f5b4a9c3SStephane Eranian "disable CPU count aggregation"), 1108d7470b6aSStephane Eranian OPT_STRING('x', "field-separator", &csv_sep, "separator", 1109d7470b6aSStephane Eranian "print counts with custom separator"), 1110023695d9SStephane Eranian OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 1111023695d9SStephane Eranian "monitor event in cgroup name only", 1112023695d9SStephane Eranian parse_cgroups), 11134aa9015fSStephane Eranian OPT_STRING('o', "output", &output_name, "file", 11144aa9015fSStephane Eranian "output file name"), 11154aa9015fSStephane Eranian OPT_BOOLEAN(0, "append", &append_file, "append to the output file"), 111656f3bae7SJim Cromie OPT_INTEGER(0, "log-fd", &output_fd, 111756f3bae7SJim Cromie "log output to fd, instead of stderr"), 111886470930SIngo Molnar OPT_END() 111986470930SIngo Molnar }; 112086470930SIngo Molnar 11212cba3ffbSIngo Molnar /* 11222cba3ffbSIngo Molnar * Add default attributes, if there were no attributes specified or 11232cba3ffbSIngo Molnar * if -d/--detailed, -d -d or -d -d -d is used: 11242cba3ffbSIngo Molnar */ 11252cba3ffbSIngo Molnar static int add_default_attributes(void) 11262cba3ffbSIngo Molnar { 11272cba3ffbSIngo Molnar /* Set attrs if no event is selected and !null_run: */ 11282cba3ffbSIngo Molnar if (null_run) 11292cba3ffbSIngo Molnar return 0; 11302cba3ffbSIngo Molnar 11312cba3ffbSIngo Molnar if (!evsel_list->nr_entries) { 113250d08e47SArnaldo Carvalho de Melo if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0) 11332cba3ffbSIngo Molnar return -1; 11342cba3ffbSIngo Molnar } 11352cba3ffbSIngo Molnar 11362cba3ffbSIngo Molnar /* Detailed events get appended to the event list: */ 11372cba3ffbSIngo Molnar 11382cba3ffbSIngo Molnar if (detailed_run < 1) 11392cba3ffbSIngo Molnar return 0; 11402cba3ffbSIngo Molnar 11412cba3ffbSIngo Molnar /* Append detailed run extra attributes: */ 114250d08e47SArnaldo Carvalho de Melo if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0) 11432cba3ffbSIngo Molnar return -1; 11442cba3ffbSIngo Molnar 11452cba3ffbSIngo Molnar if (detailed_run < 2) 11462cba3ffbSIngo Molnar return 0; 11472cba3ffbSIngo Molnar 11482cba3ffbSIngo Molnar /* Append very detailed run extra attributes: */ 114950d08e47SArnaldo Carvalho de Melo if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0) 11502cba3ffbSIngo Molnar return -1; 11512cba3ffbSIngo Molnar 11522cba3ffbSIngo Molnar if (detailed_run < 3) 11532cba3ffbSIngo Molnar return 0; 11542cba3ffbSIngo Molnar 11552cba3ffbSIngo Molnar /* Append very, very detailed run extra attributes: */ 115650d08e47SArnaldo Carvalho de Melo return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs); 11572cba3ffbSIngo Molnar } 11582cba3ffbSIngo Molnar 1159f37a291cSIngo Molnar int cmd_stat(int argc, const char **argv, const char *prefix __used) 116086470930SIngo Molnar { 116169aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 116269aad6f1SArnaldo Carvalho de Melo int status = -ENOMEM; 11634aa9015fSStephane Eranian const char *mode; 116442202dd5SIngo Molnar 11655af52b51SStephane Eranian setlocale(LC_ALL, ""); 11665af52b51SStephane Eranian 11677e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 1168361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 1169361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1170361c99a6SArnaldo Carvalho de Melo 1171a0541234SAnton Blanchard argc = parse_options(argc, argv, options, stat_usage, 1172a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1173d7470b6aSStephane Eranian 11744aa9015fSStephane Eranian output = stderr; 11754aa9015fSStephane Eranian if (output_name && strcmp(output_name, "-")) 11764aa9015fSStephane Eranian output = NULL; 11774aa9015fSStephane Eranian 117856f3bae7SJim Cromie if (output_name && output_fd) { 117956f3bae7SJim Cromie fprintf(stderr, "cannot use both --output and --log-fd\n"); 118056f3bae7SJim Cromie usage_with_options(stat_usage, options); 118156f3bae7SJim Cromie } 11824aa9015fSStephane Eranian if (!output) { 11834aa9015fSStephane Eranian struct timespec tm; 11844aa9015fSStephane Eranian mode = append_file ? "a" : "w"; 11854aa9015fSStephane Eranian 11864aa9015fSStephane Eranian output = fopen(output_name, mode); 11874aa9015fSStephane Eranian if (!output) { 11884aa9015fSStephane Eranian perror("failed to create output file"); 11894aa9015fSStephane Eranian exit(-1); 11904aa9015fSStephane Eranian } 11914aa9015fSStephane Eranian clock_gettime(CLOCK_REALTIME, &tm); 11924aa9015fSStephane Eranian fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); 119356f3bae7SJim Cromie } else if (output_fd != 2) { 119456f3bae7SJim Cromie mode = append_file ? "a" : "w"; 119556f3bae7SJim Cromie output = fdopen(output_fd, mode); 119656f3bae7SJim Cromie if (!output) { 119756f3bae7SJim Cromie perror("Failed opening logfd"); 119856f3bae7SJim Cromie return -errno; 119956f3bae7SJim Cromie } 12004aa9015fSStephane Eranian } 12014aa9015fSStephane Eranian 1202d4ffd04dSJim Cromie if (csv_sep) { 1203d7470b6aSStephane Eranian csv_output = true; 1204d4ffd04dSJim Cromie if (!strcmp(csv_sep, "\\t")) 1205d4ffd04dSJim Cromie csv_sep = "\t"; 1206d4ffd04dSJim Cromie } else 1207d7470b6aSStephane Eranian csv_sep = DEFAULT_SEPARATOR; 1208d7470b6aSStephane Eranian 1209d7470b6aSStephane Eranian /* 1210d7470b6aSStephane Eranian * let the spreadsheet do the pretty-printing 1211d7470b6aSStephane Eranian */ 1212d7470b6aSStephane Eranian if (csv_output) { 121361a9f324SJim Cromie /* User explicitly passed -B? */ 1214d7470b6aSStephane Eranian if (big_num_opt == 1) { 1215d7470b6aSStephane Eranian fprintf(stderr, "-B option not supported with -x\n"); 1216d7470b6aSStephane Eranian usage_with_options(stat_usage, options); 1217d7470b6aSStephane Eranian } else /* Nope, so disable big number formatting */ 1218d7470b6aSStephane Eranian big_num = false; 1219d7470b6aSStephane Eranian } else if (big_num_opt == 0) /* User passed --no-big-num */ 1220d7470b6aSStephane Eranian big_num = false; 1221d7470b6aSStephane Eranian 1222aa22dd49SNamhyung Kim if (!argc && !perf_target__has_task(&target)) 122386470930SIngo Molnar usage_with_options(stat_usage, options); 12249e9772c4SPeter Zijlstra if (run_count <= 0) 122542202dd5SIngo Molnar usage_with_options(stat_usage, options); 122686470930SIngo Molnar 1227023695d9SStephane Eranian /* no_aggr, cgroup are for system-wide only */ 1228aa22dd49SNamhyung Kim if ((no_aggr || nr_cgroups) && !perf_target__has_cpu(&target)) { 1229023695d9SStephane Eranian fprintf(stderr, "both cgroup and no-aggregation " 1230023695d9SStephane Eranian "modes only available in system-wide mode\n"); 1231023695d9SStephane Eranian 1232f5b4a9c3SStephane Eranian usage_with_options(stat_usage, options); 1233023695d9SStephane Eranian } 1234f5b4a9c3SStephane Eranian 12352cba3ffbSIngo Molnar if (add_default_attributes()) 1236c6264defSIngo Molnar goto out; 123786470930SIngo Molnar 12384bd0f2d2SNamhyung Kim perf_target__validate(&target); 12395c98d466SArnaldo Carvalho de Melo 124077a6f014SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &target) < 0) { 1241aa22dd49SNamhyung Kim if (perf_target__has_task(&target)) 12425c98d466SArnaldo Carvalho de Melo pr_err("Problems finding threads of monitor\n"); 1243aa22dd49SNamhyung Kim if (perf_target__has_cpu(&target)) 124460d567e2SArnaldo Carvalho de Melo perror("failed to parse CPUs map"); 124577a6f014SNamhyung Kim 1246c45c6ea2SStephane Eranian usage_with_options(stat_usage, options); 124760d567e2SArnaldo Carvalho de Melo return -1; 124860d567e2SArnaldo Carvalho de Melo } 1249c45c6ea2SStephane Eranian 1250361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 1251c52b12edSArnaldo Carvalho de Melo if (perf_evsel__alloc_stat_priv(pos) < 0 || 1252806fb630SArnaldo Carvalho de Melo perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0) 125369aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 1254d6d901c2SZhang, Yanmin } 1255d6d901c2SZhang, Yanmin 125686470930SIngo Molnar /* 125786470930SIngo Molnar * We dont want to block the signals - that would cause 125886470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 125986470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 126086470930SIngo Molnar * task, but being ignored by perf stat itself: 126186470930SIngo Molnar */ 1262f7b7c26eSPeter Zijlstra atexit(sig_atexit); 126386470930SIngo Molnar signal(SIGINT, skip_signal); 126486470930SIngo Molnar signal(SIGALRM, skip_signal); 126586470930SIngo Molnar signal(SIGABRT, skip_signal); 126686470930SIngo Molnar 126742202dd5SIngo Molnar status = 0; 126842202dd5SIngo Molnar for (run_idx = 0; run_idx < run_count; run_idx++) { 126942202dd5SIngo Molnar if (run_count != 1 && verbose) 12704aa9015fSStephane Eranian fprintf(output, "[ perf stat: executing run #%d ... ]\n", 12714aa9015fSStephane Eranian run_idx + 1); 1272f9cef0a9SIngo Molnar 1273f9cef0a9SIngo Molnar if (sync_run) 1274f9cef0a9SIngo Molnar sync(); 1275f9cef0a9SIngo Molnar 127642202dd5SIngo Molnar status = run_perf_stat(argc, argv); 127742202dd5SIngo Molnar } 127842202dd5SIngo Molnar 1279084ab9f8SArnaldo Carvalho de Melo if (status != -1) 128042202dd5SIngo Molnar print_stat(argc, argv); 128169aad6f1SArnaldo Carvalho de Melo out_free_fd: 1282361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) 128369aad6f1SArnaldo Carvalho de Melo perf_evsel__free_stat_priv(pos); 12847e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 12850015e2e1SArnaldo Carvalho de Melo out: 12860015e2e1SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 128742202dd5SIngo Molnar return status; 128886470930SIngo Molnar } 1289