| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 1 | /* | 
| Ingo Molnar | bf9e187 | 2009-06-02 23:37:05 +0200 | [diff] [blame] | 2 | * builtin-stat.c | 
|  | 3 | * | 
|  | 4 | * Builtin stat command: Give a precise performance counters summary | 
|  | 5 | * overview about any workload, CPU or specific PID. | 
|  | 6 | * | 
|  | 7 | * Sample output: | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 8 |  | 
| Ingo Molnar | bf9e187 | 2009-06-02 23:37:05 +0200 | [diff] [blame] | 9 | $ perf stat ~/hackbench 10 | 
|  | 10 | Time: 0.104 | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 11 |  | 
| Ingo Molnar | bf9e187 | 2009-06-02 23:37:05 +0200 | [diff] [blame] | 12 | Performance counter stats for '/home/mingo/hackbench': | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 13 |  | 
| Ingo Molnar | bf9e187 | 2009-06-02 23:37:05 +0200 | [diff] [blame] | 14 | 1255.538611  task clock ticks     #      10.143 CPU utilization factor | 
|  | 15 | 54011  context switches     #       0.043 M/sec | 
|  | 16 | 385  CPU migrations       #       0.000 M/sec | 
|  | 17 | 17755  pagefaults           #       0.014 M/sec | 
|  | 18 | 3808323185  CPU cycles           #    3033.219 M/sec | 
|  | 19 | 1575111190  instructions         #    1254.530 M/sec | 
|  | 20 | 17367895  cache references     #      13.833 M/sec | 
|  | 21 | 7674421  cache misses         #       6.112 M/sec | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 22 |  | 
| Ingo Molnar | bf9e187 | 2009-06-02 23:37:05 +0200 | [diff] [blame] | 23 | Wall-clock time elapsed:   123.786620 msecs | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 24 |  | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 25 | * | 
|  | 26 | * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com> | 
|  | 27 | * | 
|  | 28 | * Improvements and fixes by: | 
|  | 29 | * | 
|  | 30 | *   Arjan van de Ven <arjan@linux.intel.com> | 
|  | 31 | *   Yanmin Zhang <yanmin.zhang@intel.com> | 
|  | 32 | *   Wu Fengguang <fengguang.wu@intel.com> | 
|  | 33 | *   Mike Galbraith <efault@gmx.de> | 
|  | 34 | *   Paul Mackerras <paulus@samba.org> | 
|  | 35 | * | 
|  | 36 | * Released under the GPL v2. (and only v2, not any later version) | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 37 | */ | 
|  | 38 |  | 
| Peter Zijlstra | 1a482f3 | 2009-05-23 18:28:58 +0200 | [diff] [blame] | 39 | #include "perf.h" | 
| Ingo Molnar | 16f762a | 2009-05-27 09:10:38 +0200 | [diff] [blame] | 40 | #include "builtin.h" | 
| Ingo Molnar | 148be2c | 2009-04-27 08:02:14 +0200 | [diff] [blame] | 41 | #include "util/util.h" | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 42 | #include "util/parse-options.h" | 
|  | 43 | #include "util/parse-events.h" | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 44 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 45 | #include <sys/prctl.h> | 
| Peter Zijlstra | 16c8a10 | 2009-05-05 17:50:27 +0200 | [diff] [blame] | 46 |  | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 47 | static struct perf_counter_attr default_attrs[MAX_COUNTERS] = { | 
|  | 48 |  | 
|  | 49 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_TASK_CLOCK		}, | 
|  | 50 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_CONTEXT_SWITCHES	}, | 
|  | 51 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_CPU_MIGRATIONS	}, | 
|  | 52 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_PAGE_FAULTS	}, | 
|  | 53 |  | 
|  | 54 | { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CPU_CYCLES		}, | 
|  | 55 | { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_INSTRUCTIONS	}, | 
|  | 56 | { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CACHE_REFERENCES	}, | 
|  | 57 | { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CACHE_MISSES	}, | 
|  | 58 | }; | 
|  | 59 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 60 | static int			system_wide			=  0; | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 61 | static int			inherit				=  1; | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 62 | static int			verbose				=  0; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 63 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 64 | static int			fd[MAX_NR_CPUS][MAX_COUNTERS]; | 
|  | 65 |  | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 66 | static int			target_pid			= -1; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 67 | static int			nr_cpus				=  0; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 68 | static unsigned int		page_size; | 
|  | 69 |  | 
| Ingo Molnar | 66cf782 | 2009-04-30 13:53:33 +0200 | [diff] [blame] | 70 | static int			scale				=  1; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 71 |  | 
|  | 72 | static const unsigned int default_count[] = { | 
|  | 73 | 1000000, | 
|  | 74 | 1000000, | 
|  | 75 | 10000, | 
|  | 76 | 10000, | 
|  | 77 | 1000000, | 
|  | 78 | 10000, | 
|  | 79 | }; | 
|  | 80 |  | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 81 | static __u64			event_res[MAX_COUNTERS][3]; | 
|  | 82 | static __u64			event_scaled[MAX_COUNTERS]; | 
|  | 83 |  | 
| Ingo Molnar | be1ac0d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 84 | static __u64			runtime_nsecs; | 
| Ingo Molnar | d7c2931 | 2009-05-30 12:38:51 +0200 | [diff] [blame] | 85 | static __u64			walltime_nsecs; | 
| Ingo Molnar | be1ac0d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 86 |  | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 87 | static void create_perf_stat_counter(int counter) | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 88 | { | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 89 | struct perf_counter_attr *attr = attrs + counter; | 
| Peter Zijlstra | 16c8a10 | 2009-05-05 17:50:27 +0200 | [diff] [blame] | 90 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 91 | if (scale) | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 92 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | | 
|  | 93 | PERF_FORMAT_TOTAL_TIME_RUNNING; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 94 |  | 
|  | 95 | if (system_wide) { | 
|  | 96 | int cpu; | 
|  | 97 | for (cpu = 0; cpu < nr_cpus; cpu ++) { | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 98 | fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 99 | if (fd[cpu][counter] < 0 && verbose) { | 
|  | 100 | printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[cpu][counter], strerror(errno)); | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 101 | } | 
|  | 102 | } | 
|  | 103 | } else { | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 104 | attr->inherit	= inherit; | 
|  | 105 | attr->disabled	= 1; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 106 |  | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 107 | fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0); | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 108 | if (fd[0][counter] < 0 && verbose) { | 
|  | 109 | printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[0][counter], strerror(errno)); | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 110 | } | 
|  | 111 | } | 
|  | 112 | } | 
|  | 113 |  | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 114 | /* | 
|  | 115 | * Does the counter have nsecs as a unit? | 
|  | 116 | */ | 
|  | 117 | static inline int nsec_counter(int counter) | 
|  | 118 | { | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 119 | if (attrs[counter].type != PERF_TYPE_SOFTWARE) | 
|  | 120 | return 0; | 
|  | 121 |  | 
|  | 122 | if (attrs[counter].config == PERF_COUNT_CPU_CLOCK) | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 123 | return 1; | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 124 |  | 
|  | 125 | if (attrs[counter].config == PERF_COUNT_TASK_CLOCK) | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 126 | return 1; | 
|  | 127 |  | 
|  | 128 | return 0; | 
|  | 129 | } | 
|  | 130 |  | 
|  | 131 | /* | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 132 | * Read out the results of a single counter: | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 133 | */ | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 134 | static void read_counter(int counter) | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 135 | { | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 136 | __u64 *count, single_count[3]; | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 137 | ssize_t res; | 
|  | 138 | int cpu, nv; | 
|  | 139 | int scaled; | 
|  | 140 |  | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 141 | count = event_res[counter]; | 
|  | 142 |  | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 143 | count[0] = count[1] = count[2] = 0; | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 144 |  | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 145 | nv = scale ? 3 : 1; | 
|  | 146 | for (cpu = 0; cpu < nr_cpus; cpu ++) { | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 147 | if (fd[cpu][counter] < 0) | 
|  | 148 | continue; | 
|  | 149 |  | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 150 | res = read(fd[cpu][counter], single_count, nv * sizeof(__u64)); | 
|  | 151 | assert(res == nv * sizeof(__u64)); | 
|  | 152 |  | 
|  | 153 | count[0] += single_count[0]; | 
|  | 154 | if (scale) { | 
|  | 155 | count[1] += single_count[1]; | 
|  | 156 | count[2] += single_count[2]; | 
|  | 157 | } | 
|  | 158 | } | 
|  | 159 |  | 
|  | 160 | scaled = 0; | 
|  | 161 | if (scale) { | 
|  | 162 | if (count[2] == 0) { | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 163 | event_scaled[counter] = -1; | 
|  | 164 | count[0] = 0; | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 165 | return; | 
|  | 166 | } | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 167 |  | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 168 | if (count[2] < count[1]) { | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 169 | event_scaled[counter] = 1; | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 170 | count[0] = (unsigned long long) | 
|  | 171 | ((double)count[0] * count[1] / count[2] + 0.5); | 
|  | 172 | } | 
|  | 173 | } | 
| Ingo Molnar | be1ac0d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 174 | /* | 
|  | 175 | * Save the full runtime - to allow normalization during printout: | 
|  | 176 | */ | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 177 | if (attrs[counter].type == PERF_TYPE_SOFTWARE && | 
|  | 178 | attrs[counter].config == PERF_COUNT_TASK_CLOCK) | 
| Ingo Molnar | be1ac0d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 179 | runtime_nsecs = count[0]; | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 180 | } | 
|  | 181 |  | 
|  | 182 | /* | 
|  | 183 | * Print out the results of a single counter: | 
|  | 184 | */ | 
|  | 185 | static void print_counter(int counter) | 
|  | 186 | { | 
|  | 187 | __u64 *count; | 
|  | 188 | int scaled; | 
|  | 189 |  | 
|  | 190 | count = event_res[counter]; | 
|  | 191 | scaled = event_scaled[counter]; | 
|  | 192 |  | 
|  | 193 | if (scaled == -1) { | 
|  | 194 | fprintf(stderr, " %14s  %-20s\n", | 
|  | 195 | "<not counted>", event_name(counter)); | 
|  | 196 | return; | 
|  | 197 | } | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 198 |  | 
|  | 199 | if (nsec_counter(counter)) { | 
|  | 200 | double msecs = (double)count[0] / 1000000; | 
|  | 201 |  | 
| Ingo Molnar | d7c2931 | 2009-05-30 12:38:51 +0200 | [diff] [blame] | 202 | fprintf(stderr, " %14.6f  %-20s", | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 203 | msecs, event_name(counter)); | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 204 | if (attrs[counter].type == PERF_TYPE_SOFTWARE && | 
|  | 205 | attrs[counter].config == PERF_COUNT_TASK_CLOCK) { | 
| Ingo Molnar | d7c2931 | 2009-05-30 12:38:51 +0200 | [diff] [blame] | 206 |  | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 207 | if (walltime_nsecs) | 
|  | 208 | fprintf(stderr, " # %11.3f CPU utilization factor", | 
|  | 209 | (double)count[0] / (double)walltime_nsecs); | 
| Ingo Molnar | d7c2931 | 2009-05-30 12:38:51 +0200 | [diff] [blame] | 210 | } | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 211 | } else { | 
| Ingo Molnar | be1ac0d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 212 | fprintf(stderr, " %14Ld  %-20s", | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 213 | count[0], event_name(counter)); | 
| Ingo Molnar | be1ac0d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 214 | if (runtime_nsecs) | 
| Ingo Molnar | d7c2931 | 2009-05-30 12:38:51 +0200 | [diff] [blame] | 215 | fprintf(stderr, " # %11.3f M/sec", | 
| Ingo Molnar | be1ac0d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 216 | (double)count[0]/runtime_nsecs*1000.0); | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 217 | } | 
|  | 218 | if (scaled) | 
|  | 219 | fprintf(stderr, "  (scaled from %.2f%%)", | 
|  | 220 | (double) count[2] / count[1] * 100); | 
|  | 221 | fprintf(stderr, "\n"); | 
|  | 222 | } | 
|  | 223 |  | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 224 | static int do_perf_stat(int argc, const char **argv) | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 225 | { | 
|  | 226 | unsigned long long t0, t1; | 
|  | 227 | int counter; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 228 | int status; | 
|  | 229 | int pid; | 
| Ingo Molnar | 44db76c | 2009-06-03 19:36:07 +0200 | [diff] [blame] | 230 | int i; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 231 |  | 
|  | 232 | if (!system_wide) | 
|  | 233 | nr_cpus = 1; | 
|  | 234 |  | 
|  | 235 | for (counter = 0; counter < nr_counters; counter++) | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 236 | create_perf_stat_counter(counter); | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 237 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 238 | /* | 
|  | 239 | * Enable counters and exec the command: | 
|  | 240 | */ | 
|  | 241 | t0 = rdclock(); | 
|  | 242 | prctl(PR_TASK_PERF_COUNTERS_ENABLE); | 
|  | 243 |  | 
|  | 244 | if ((pid = fork()) < 0) | 
|  | 245 | perror("failed to fork"); | 
| Ingo Molnar | 44db76c | 2009-06-03 19:36:07 +0200 | [diff] [blame] | 246 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 247 | if (!pid) { | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 248 | if (execvp(argv[0], (char **)argv)) { | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 249 | perror(argv[0]); | 
|  | 250 | exit(-1); | 
|  | 251 | } | 
|  | 252 | } | 
| Ingo Molnar | 44db76c | 2009-06-03 19:36:07 +0200 | [diff] [blame] | 253 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 254 | while (wait(&status) >= 0) | 
|  | 255 | ; | 
| Ingo Molnar | 44db76c | 2009-06-03 19:36:07 +0200 | [diff] [blame] | 256 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 257 | prctl(PR_TASK_PERF_COUNTERS_DISABLE); | 
|  | 258 | t1 = rdclock(); | 
|  | 259 |  | 
| Ingo Molnar | d7c2931 | 2009-05-30 12:38:51 +0200 | [diff] [blame] | 260 | walltime_nsecs = t1 - t0; | 
|  | 261 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 262 | fflush(stdout); | 
|  | 263 |  | 
|  | 264 | fprintf(stderr, "\n"); | 
| Ingo Molnar | 44db76c | 2009-06-03 19:36:07 +0200 | [diff] [blame] | 265 | fprintf(stderr, " Performance counter stats for \'%s", argv[0]); | 
|  | 266 |  | 
|  | 267 | for (i = 1; i < argc; i++) | 
|  | 268 | fprintf(stderr, " %s", argv[i]); | 
|  | 269 |  | 
|  | 270 | fprintf(stderr, "\':\n"); | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 271 | fprintf(stderr, "\n"); | 
|  | 272 |  | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 273 | for (counter = 0; counter < nr_counters; counter++) | 
| Ingo Molnar | 2996f5d | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 274 | read_counter(counter); | 
|  | 275 |  | 
|  | 276 | for (counter = 0; counter < nr_counters; counter++) | 
| Ingo Molnar | c04f5e5 | 2009-05-29 09:10:54 +0200 | [diff] [blame] | 277 | print_counter(counter); | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 278 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 279 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 280 | fprintf(stderr, "\n"); | 
|  | 281 | fprintf(stderr, " Wall-clock time elapsed: %12.6f msecs\n", | 
|  | 282 | (double)(t1-t0)/1e6); | 
|  | 283 | fprintf(stderr, "\n"); | 
|  | 284 |  | 
|  | 285 | return 0; | 
|  | 286 | } | 
|  | 287 |  | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 288 | static void skip_signal(int signo) | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 289 | { | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 290 | } | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 291 |  | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 292 | static const char * const stat_usage[] = { | 
|  | 293 | "perf stat [<options>] <command>", | 
|  | 294 | NULL | 
|  | 295 | }; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 296 |  | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 297 | static const struct option options[] = { | 
|  | 298 | OPT_CALLBACK('e', "event", NULL, "event", | 
| Thomas Gleixner | 86847b6 | 2009-06-06 12:24:17 +0200 | [diff] [blame] | 299 | "event selector. use 'perf list' to list available events", | 
|  | 300 | parse_events), | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 301 | OPT_BOOLEAN('i', "inherit", &inherit, | 
|  | 302 | "child tasks inherit counters"), | 
|  | 303 | OPT_INTEGER('p', "pid", &target_pid, | 
|  | 304 | "stat events on existing pid"), | 
|  | 305 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 
|  | 306 | "system-wide collection from all CPUs"), | 
| Thomas Gleixner | 86847b6 | 2009-06-06 12:24:17 +0200 | [diff] [blame] | 307 | OPT_BOOLEAN('S', "scale", &scale, | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 308 | "scale/normalize counters"), | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 309 | OPT_BOOLEAN('v', "verbose", &verbose, | 
|  | 310 | "be more verbose (show counter open errors, etc)"), | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 311 | OPT_END() | 
|  | 312 | }; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 313 |  | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 314 | int cmd_stat(int argc, const char **argv, const char *prefix) | 
|  | 315 | { | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 316 | page_size = sysconf(_SC_PAGE_SIZE); | 
|  | 317 |  | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 318 | memcpy(attrs, default_attrs, sizeof(attrs)); | 
| Ingo Molnar | 5242519 | 2009-05-26 09:17:18 +0200 | [diff] [blame] | 319 |  | 
|  | 320 | argc = parse_options(argc, argv, options, stat_usage, 0); | 
|  | 321 | if (!argc) | 
|  | 322 | usage_with_options(stat_usage, options); | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 323 |  | 
| Ingo Molnar | a21ca2c | 2009-06-06 09:58:57 +0200 | [diff] [blame] | 324 | if (!nr_counters) | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 325 | nr_counters = 8; | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 326 |  | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 327 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | 
|  | 328 | assert(nr_cpus <= MAX_NR_CPUS); | 
|  | 329 | assert(nr_cpus >= 0); | 
|  | 330 |  | 
| Ingo Molnar | 58d7e99 | 2009-05-15 11:03:23 +0200 | [diff] [blame] | 331 | /* | 
|  | 332 | * We dont want to block the signals - that would cause | 
|  | 333 | * child tasks to inherit that and Ctrl-C would not work. | 
|  | 334 | * What we want is for Ctrl-C to work in the exec()-ed | 
|  | 335 | * task, but being ignored by perf stat itself: | 
|  | 336 | */ | 
|  | 337 | signal(SIGINT,  skip_signal); | 
|  | 338 | signal(SIGALRM, skip_signal); | 
|  | 339 | signal(SIGABRT, skip_signal); | 
|  | 340 |  | 
| Ingo Molnar | 743ee1f | 2009-06-07 17:06:46 +0200 | [diff] [blame^] | 341 | return do_perf_stat(argc, argv); | 
| Ingo Molnar | ddcacfa | 2009-04-20 15:37:32 +0200 | [diff] [blame] | 342 | } |