diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-03 14:45:52 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-03 21:22:55 -0500 |
commit | c52b12ed2511e6c031a0295fd903ea72b93701fb (patch) | |
tree | 770915627e789401b820a104c1ed23a212e7bd50 /tools/perf/builtin-stat.c | |
parent | 70d544d0576775a2b3923a7e68cb49b0313d80c9 (diff) |
perf evsel: Steal the counter reading routines from stat
Making them hopefully generic enough to be used in 'perf test',
well see.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r-- | tools/perf/builtin-stat.c | 121 |
1 files changed, 29 insertions, 92 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 589ba3a92423..a8b00b44b3cd 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -93,12 +93,6 @@ static const char *cpu_list; | |||
93 | static const char *csv_sep = NULL; | 93 | static const char *csv_sep = NULL; |
94 | static bool csv_output = false; | 94 | static bool csv_output = false; |
95 | 95 | ||
96 | struct cpu_counts { | ||
97 | u64 val; | ||
98 | u64 ena; | ||
99 | u64 run; | ||
100 | }; | ||
101 | |||
102 | static volatile int done = 0; | 96 | static volatile int done = 0; |
103 | 97 | ||
104 | struct stats | 98 | struct stats |
@@ -108,15 +102,11 @@ struct stats | |||
108 | 102 | ||
109 | struct perf_stat { | 103 | struct perf_stat { |
110 | struct stats res_stats[3]; | 104 | struct stats res_stats[3]; |
111 | int scaled; | ||
112 | struct cpu_counts cpu_counts[]; | ||
113 | }; | 105 | }; |
114 | 106 | ||
115 | static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel, int ncpus) | 107 | static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) |
116 | { | 108 | { |
117 | size_t priv_size = (sizeof(struct perf_stat) + | 109 | evsel->priv = zalloc(sizeof(struct perf_stat)); |
118 | (ncpus * sizeof(struct cpu_counts))); | ||
119 | evsel->priv = zalloc(priv_size); | ||
120 | return evsel->priv == NULL ? -ENOMEM : 0; | 110 | return evsel->priv == NULL ? -ENOMEM : 0; |
121 | } | 111 | } |
122 | 112 | ||
@@ -238,52 +228,14 @@ static inline int nsec_counter(struct perf_evsel *evsel) | |||
238 | * Read out the results of a single counter: | 228 | * Read out the results of a single counter: |
239 | * aggregate counts across CPUs in system-wide mode | 229 | * aggregate counts across CPUs in system-wide mode |
240 | */ | 230 | */ |
241 | static void read_counter_aggr(struct perf_evsel *counter) | 231 | static int read_counter_aggr(struct perf_evsel *counter) |
242 | { | 232 | { |
243 | struct perf_stat *ps = counter->priv; | 233 | struct perf_stat *ps = counter->priv; |
244 | u64 count[3], single_count[3]; | 234 | u64 *count = counter->counts->aggr.values; |
245 | int cpu; | 235 | int i; |
246 | size_t res, nv; | ||
247 | int scaled; | ||
248 | int i, thread; | ||
249 | |||
250 | count[0] = count[1] = count[2] = 0; | ||
251 | |||
252 | nv = scale ? 3 : 1; | ||
253 | for (cpu = 0; cpu < nr_cpus; cpu++) { | ||
254 | for (thread = 0; thread < thread_num; thread++) { | ||
255 | if (FD(counter, cpu, thread) < 0) | ||
256 | continue; | ||
257 | |||
258 | res = read(FD(counter, cpu, thread), | ||
259 | single_count, nv * sizeof(u64)); | ||
260 | assert(res == nv * sizeof(u64)); | ||
261 | |||
262 | close(FD(counter, cpu, thread)); | ||
263 | FD(counter, cpu, thread) = -1; | ||
264 | |||
265 | count[0] += single_count[0]; | ||
266 | if (scale) { | ||
267 | count[1] += single_count[1]; | ||
268 | count[2] += single_count[2]; | ||
269 | } | ||
270 | } | ||
271 | } | ||
272 | |||
273 | scaled = 0; | ||
274 | if (scale) { | ||
275 | if (count[2] == 0) { | ||
276 | ps->scaled = -1; | ||
277 | count[0] = 0; | ||
278 | return; | ||
279 | } | ||
280 | 236 | ||
281 | if (count[2] < count[1]) { | 237 | if (__perf_evsel__read(counter, nr_cpus, thread_num, scale) < 0) |
282 | ps->scaled = 1; | 238 | return -1; |
283 | count[0] = (unsigned long long) | ||
284 | ((double)count[0] * count[1] / count[2] + 0.5); | ||
285 | } | ||
286 | } | ||
287 | 239 | ||
288 | for (i = 0; i < 3; i++) | 240 | for (i = 0; i < 3; i++) |
289 | update_stats(&ps->res_stats[i], count[i]); | 241 | update_stats(&ps->res_stats[i], count[i]); |
@@ -302,46 +254,24 @@ static void read_counter_aggr(struct perf_evsel *counter) | |||
302 | update_stats(&runtime_cycles_stats[0], count[0]); | 254 | update_stats(&runtime_cycles_stats[0], count[0]); |
303 | if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) | 255 | if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) |
304 | update_stats(&runtime_branches_stats[0], count[0]); | 256 | update_stats(&runtime_branches_stats[0], count[0]); |
257 | |||
258 | return 0; | ||
305 | } | 259 | } |
306 | 260 | ||
307 | /* | 261 | /* |
308 | * Read out the results of a single counter: | 262 | * Read out the results of a single counter: |
309 | * do not aggregate counts across CPUs in system-wide mode | 263 | * do not aggregate counts across CPUs in system-wide mode |
310 | */ | 264 | */ |
311 | static void read_counter(struct perf_evsel *counter) | 265 | static int read_counter(struct perf_evsel *counter) |
312 | { | 266 | { |
313 | struct cpu_counts *cpu_counts = counter->priv; | 267 | u64 *count; |
314 | u64 count[3]; | ||
315 | int cpu; | 268 | int cpu; |
316 | size_t res, nv; | ||
317 | |||
318 | count[0] = count[1] = count[2] = 0; | ||
319 | |||
320 | nv = scale ? 3 : 1; | ||
321 | 269 | ||
322 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 270 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
271 | if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) | ||
272 | return -1; | ||
323 | 273 | ||
324 | if (FD(counter, cpu, 0) < 0) | 274 | count = counter->counts->cpu[cpu].values; |
325 | continue; | ||
326 | |||
327 | res = read(FD(counter, cpu, 0), count, nv * sizeof(u64)); | ||
328 | |||
329 | assert(res == nv * sizeof(u64)); | ||
330 | |||
331 | close(FD(counter, cpu, 0)); | ||
332 | FD(counter, cpu, 0) = -1; | ||
333 | |||
334 | if (scale) { | ||
335 | if (count[2] == 0) { | ||
336 | count[0] = 0; | ||
337 | } else if (count[2] < count[1]) { | ||
338 | count[0] = (unsigned long long) | ||
339 | ((double)count[0] * count[1] / count[2] + 0.5); | ||
340 | } | ||
341 | } | ||
342 | cpu_counts[cpu].val = count[0]; /* scaled count */ | ||
343 | cpu_counts[cpu].ena = count[1]; | ||
344 | cpu_counts[cpu].run = count[2]; | ||
345 | 275 | ||
346 | if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) | 276 | if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) |
347 | update_stats(&runtime_nsecs_stats[cpu], count[0]); | 277 | update_stats(&runtime_nsecs_stats[cpu], count[0]); |
@@ -350,6 +280,8 @@ static void read_counter(struct perf_evsel *counter) | |||
350 | if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) | 280 | if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) |
351 | update_stats(&runtime_branches_stats[cpu], count[0]); | 281 | update_stats(&runtime_branches_stats[cpu], count[0]); |
352 | } | 282 | } |
283 | |||
284 | return 0; | ||
353 | } | 285 | } |
354 | 286 | ||
355 | static int run_perf_stat(int argc __used, const char **argv) | 287 | static int run_perf_stat(int argc __used, const char **argv) |
@@ -449,12 +381,17 @@ static int run_perf_stat(int argc __used, const char **argv) | |||
449 | update_stats(&walltime_nsecs_stats, t1 - t0); | 381 | update_stats(&walltime_nsecs_stats, t1 - t0); |
450 | 382 | ||
451 | if (no_aggr) { | 383 | if (no_aggr) { |
452 | list_for_each_entry(counter, &evsel_list, node) | 384 | list_for_each_entry(counter, &evsel_list, node) { |
453 | read_counter(counter); | 385 | read_counter(counter); |
386 | perf_evsel__close_fd(counter, nr_cpus, 1); | ||
387 | } | ||
454 | } else { | 388 | } else { |
455 | list_for_each_entry(counter, &evsel_list, node) | 389 | list_for_each_entry(counter, &evsel_list, node) { |
456 | read_counter_aggr(counter); | 390 | read_counter_aggr(counter); |
391 | perf_evsel__close_fd(counter, nr_cpus, thread_num); | ||
392 | } | ||
457 | } | 393 | } |
394 | |||
458 | return WEXITSTATUS(status); | 395 | return WEXITSTATUS(status); |
459 | } | 396 | } |
460 | 397 | ||
@@ -550,7 +487,7 @@ static void print_counter_aggr(struct perf_evsel *counter) | |||
550 | { | 487 | { |
551 | struct perf_stat *ps = counter->priv; | 488 | struct perf_stat *ps = counter->priv; |
552 | double avg = avg_stats(&ps->res_stats[0]); | 489 | double avg = avg_stats(&ps->res_stats[0]); |
553 | int scaled = ps->scaled; | 490 | int scaled = counter->counts->scaled; |
554 | 491 | ||
555 | if (scaled == -1) { | 492 | if (scaled == -1) { |
556 | fprintf(stderr, "%*s%s%-24s\n", | 493 | fprintf(stderr, "%*s%s%-24s\n", |
@@ -590,14 +527,13 @@ static void print_counter_aggr(struct perf_evsel *counter) | |||
590 | */ | 527 | */ |
591 | static void print_counter(struct perf_evsel *counter) | 528 | static void print_counter(struct perf_evsel *counter) |
592 | { | 529 | { |
593 | struct perf_stat *ps = counter->priv; | ||
594 | u64 ena, run, val; | 530 | u64 ena, run, val; |
595 | int cpu; | 531 | int cpu; |
596 | 532 | ||
597 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 533 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
598 | val = ps->cpu_counts[cpu].val; | 534 | val = counter->counts->cpu[cpu].val; |
599 | ena = ps->cpu_counts[cpu].ena; | 535 | ena = counter->counts->cpu[cpu].ena; |
600 | run = ps->cpu_counts[cpu].run; | 536 | run = counter->counts->cpu[cpu].run; |
601 | if (run == 0 || ena == 0) { | 537 | if (run == 0 || ena == 0) { |
602 | fprintf(stderr, "CPU%*d%s%*s%s%-24s", | 538 | fprintf(stderr, "CPU%*d%s%*s%s%-24s", |
603 | csv_output ? 0 : -4, | 539 | csv_output ? 0 : -4, |
@@ -818,7 +754,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) | |||
818 | } | 754 | } |
819 | 755 | ||
820 | list_for_each_entry(pos, &evsel_list, node) { | 756 | list_for_each_entry(pos, &evsel_list, node) { |
821 | if (perf_evsel__alloc_stat_priv(pos, nr_cpus) < 0 || | 757 | if (perf_evsel__alloc_stat_priv(pos) < 0 || |
758 | perf_evsel__alloc_counts(pos, nr_cpus) < 0 || | ||
822 | perf_evsel__alloc_fd(pos, nr_cpus, thread_num) < 0) | 759 | perf_evsel__alloc_fd(pos, nr_cpus, thread_num) < 0) |
823 | goto out_free_fd; | 760 | goto out_free_fd; |
824 | } | 761 | } |