aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2013-10-30 03:06:59 -0400
committerJiri Olsa <jolsa@kernel.org>2014-06-01 08:35:00 -0400
commit594dcbf3186e2e1e5c08fa21e8826b90d347f23f (patch)
tree04af47780d4cdc8b4cb205a554cd76bf834b3ba9 /tools/perf
parentbe7f855a3eebe07f797b9e4a43bf59bab8ca3dbe (diff)
perf ui/hist: Add support to accumulated hist stat
Print accumulated stat of a hist entry if requested. To do that, add new HPP_PERCENT_ACC_FNS macro and generate a perf_hpp_fmt using it. The __hpp__sort_acc() function sorts entries by accumulated period value. When accumulated periods of two entries are same (i.e. single path callchain) put the caller above since accumulation tends to put callers on higher position for obvious reason. Also add "overhead_children" output field to be selected by user. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Tested-by: Arun Sharma <asharma@fb.com> Tested-by: Rodrigo Campos <rodrigo@sdfg.com.ar> Cc: Frederic Weisbecker <fweisbec@gmail.com> Link: http://lkml.kernel.org/r/1401335910-16832-11-git-send-email-namhyung@kernel.org Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/ui/hist.c99
-rw-r--r--tools/perf/util/hist.h4
-rw-r--r--tools/perf/util/sort.c1
3 files changed, 104 insertions, 0 deletions
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 4484f5bd1b14..0ce3e79b2ca7 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -104,6 +104,18 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
104 return ret; 104 return ret;
105} 105}
106 106
107int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he,
108 hpp_field_fn get_field, const char *fmt,
109 hpp_snprint_fn print_fn, bool fmt_percent)
110{
111 if (!symbol_conf.cumulate_callchain) {
112 return snprintf(hpp->buf, hpp->size, "%*s",
113 fmt_percent ? 8 : 12, "N/A");
114 }
115
116 return __hpp__fmt(hpp, he, get_field, fmt, print_fn, fmt_percent);
117}
118
107static int field_cmp(u64 field_a, u64 field_b) 119static int field_cmp(u64 field_a, u64 field_b)
108{ 120{
109 if (field_a > field_b) 121 if (field_a > field_b)
@@ -160,6 +172,24 @@ out:
160 return ret; 172 return ret;
161} 173}
162 174
175static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
176 hpp_field_fn get_field)
177{
178 s64 ret = 0;
179
180 if (symbol_conf.cumulate_callchain) {
181 /*
182 * Put caller above callee when they have equal period.
183 */
184 ret = field_cmp(get_field(a), get_field(b));
185 if (ret)
186 return ret;
187
188 ret = b->callchain->max_depth - a->callchain->max_depth;
189 }
190 return ret;
191}
192
163#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 193#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
164static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 194static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
165 struct perf_hpp *hpp, \ 195 struct perf_hpp *hpp, \
@@ -242,6 +272,34 @@ static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \
242 return __hpp__sort(a, b, he_get_##_field); \ 272 return __hpp__sort(a, b, he_get_##_field); \
243} 273}
244 274
275#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
276static u64 he_get_acc_##_field(struct hist_entry *he) \
277{ \
278 return he->stat_acc->_field; \
279} \
280 \
281static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
282 struct perf_hpp *hpp, struct hist_entry *he) \
283{ \
284 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \
285 hpp_color_scnprintf, true); \
286}
287
288#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
289static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \
290 struct perf_hpp *hpp, struct hist_entry *he) \
291{ \
292 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \
293 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, fmt, \
294 hpp_entry_scnprintf, true); \
295}
296
297#define __HPP_SORT_ACC_FN(_type, _field) \
298static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \
299{ \
300 return __hpp__sort_acc(a, b, he_get_acc_##_field); \
301}
302
245#define __HPP_ENTRY_RAW_FN(_type, _field) \ 303#define __HPP_ENTRY_RAW_FN(_type, _field) \
246static u64 he_get_raw_##_field(struct hist_entry *he) \ 304static u64 he_get_raw_##_field(struct hist_entry *he) \
247{ \ 305{ \
@@ -270,18 +328,27 @@ __HPP_COLOR_PERCENT_FN(_type, _field) \
270__HPP_ENTRY_PERCENT_FN(_type, _field) \ 328__HPP_ENTRY_PERCENT_FN(_type, _field) \
271__HPP_SORT_FN(_type, _field) 329__HPP_SORT_FN(_type, _field)
272 330
331#define HPP_PERCENT_ACC_FNS(_type, _str, _field, _min_width, _unit_width)\
332__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
333__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
334__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
335__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
336__HPP_SORT_ACC_FN(_type, _field)
337
273#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width) \ 338#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width) \
274__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 339__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
275__HPP_WIDTH_FN(_type, _min_width, _unit_width) \ 340__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
276__HPP_ENTRY_RAW_FN(_type, _field) \ 341__HPP_ENTRY_RAW_FN(_type, _field) \
277__HPP_SORT_RAW_FN(_type, _field) 342__HPP_SORT_RAW_FN(_type, _field)
278 343
344__HPP_HEADER_FN(overhead_self, "Self", 8, 8)
279 345
280HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8) 346HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8)
281HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8) 347HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8)
282HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8) 348HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8)
283HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8) 349HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8)
284HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8) 350HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
351HPP_PERCENT_ACC_FNS(overhead_acc, "Children", period, 8, 8)
285 352
286HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) 353HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12)
287HPP_RAW_FNS(period, "Period", period, 12, 12) 354HPP_RAW_FNS(period, "Period", period, 12, 12)
@@ -303,6 +370,17 @@ static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
303 .sort = hpp__sort_ ## _name, \ 370 .sort = hpp__sort_ ## _name, \
304 } 371 }
305 372
373#define HPP__COLOR_ACC_PRINT_FNS(_name) \
374 { \
375 .header = hpp__header_ ## _name, \
376 .width = hpp__width_ ## _name, \
377 .color = hpp__color_ ## _name, \
378 .entry = hpp__entry_ ## _name, \
379 .cmp = hpp__nop_cmp, \
380 .collapse = hpp__nop_cmp, \
381 .sort = hpp__sort_ ## _name, \
382 }
383
306#define HPP__PRINT_FNS(_name) \ 384#define HPP__PRINT_FNS(_name) \
307 { \ 385 { \
308 .header = hpp__header_ ## _name, \ 386 .header = hpp__header_ ## _name, \
@@ -319,6 +397,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
319 HPP__COLOR_PRINT_FNS(overhead_us), 397 HPP__COLOR_PRINT_FNS(overhead_us),
320 HPP__COLOR_PRINT_FNS(overhead_guest_sys), 398 HPP__COLOR_PRINT_FNS(overhead_guest_sys),
321 HPP__COLOR_PRINT_FNS(overhead_guest_us), 399 HPP__COLOR_PRINT_FNS(overhead_guest_us),
400 HPP__COLOR_ACC_PRINT_FNS(overhead_acc),
322 HPP__PRINT_FNS(samples), 401 HPP__PRINT_FNS(samples),
323 HPP__PRINT_FNS(period) 402 HPP__PRINT_FNS(period)
324}; 403};
@@ -328,16 +407,23 @@ LIST_HEAD(perf_hpp__sort_list);
328 407
329 408
330#undef HPP__COLOR_PRINT_FNS 409#undef HPP__COLOR_PRINT_FNS
410#undef HPP__COLOR_ACC_PRINT_FNS
331#undef HPP__PRINT_FNS 411#undef HPP__PRINT_FNS
332 412
333#undef HPP_PERCENT_FNS 413#undef HPP_PERCENT_FNS
414#undef HPP_PERCENT_ACC_FNS
334#undef HPP_RAW_FNS 415#undef HPP_RAW_FNS
335 416
336#undef __HPP_HEADER_FN 417#undef __HPP_HEADER_FN
337#undef __HPP_WIDTH_FN 418#undef __HPP_WIDTH_FN
338#undef __HPP_COLOR_PERCENT_FN 419#undef __HPP_COLOR_PERCENT_FN
339#undef __HPP_ENTRY_PERCENT_FN 420#undef __HPP_ENTRY_PERCENT_FN
421#undef __HPP_COLOR_ACC_PERCENT_FN
422#undef __HPP_ENTRY_ACC_PERCENT_FN
340#undef __HPP_ENTRY_RAW_FN 423#undef __HPP_ENTRY_RAW_FN
424#undef __HPP_SORT_FN
425#undef __HPP_SORT_ACC_FN
426#undef __HPP_SORT_RAW_FN
341 427
342 428
343void perf_hpp__init(void) 429void perf_hpp__init(void)
@@ -361,6 +447,13 @@ void perf_hpp__init(void)
361 if (field_order) 447 if (field_order)
362 return; 448 return;
363 449
450 if (symbol_conf.cumulate_callchain) {
451 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC);
452
453 perf_hpp__format[PERF_HPP__OVERHEAD].header =
454 hpp__header_overhead_self;
455 }
456
364 perf_hpp__column_enable(PERF_HPP__OVERHEAD); 457 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
365 458
366 if (symbol_conf.show_cpu_utilization) { 459 if (symbol_conf.show_cpu_utilization) {
@@ -383,6 +476,12 @@ void perf_hpp__init(void)
383 list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list; 476 list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list;
384 if (list_empty(list)) 477 if (list_empty(list))
385 list_add(list, &perf_hpp__sort_list); 478 list_add(list, &perf_hpp__sort_list);
479
480 if (symbol_conf.cumulate_callchain) {
481 list = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC].sort_list;
482 if (list_empty(list))
483 list_add(list, &perf_hpp__sort_list);
484 }
386} 485}
387 486
388void perf_hpp__column_register(struct perf_hpp_fmt *format) 487void perf_hpp__column_register(struct perf_hpp_fmt *format)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 78409f95d012..efd73e489027 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -228,6 +228,7 @@ enum {
228 PERF_HPP__OVERHEAD_US, 228 PERF_HPP__OVERHEAD_US,
229 PERF_HPP__OVERHEAD_GUEST_SYS, 229 PERF_HPP__OVERHEAD_GUEST_SYS,
230 PERF_HPP__OVERHEAD_GUEST_US, 230 PERF_HPP__OVERHEAD_GUEST_US,
231 PERF_HPP__OVERHEAD_ACC,
231 PERF_HPP__SAMPLES, 232 PERF_HPP__SAMPLES,
232 PERF_HPP__PERIOD, 233 PERF_HPP__PERIOD,
233 234
@@ -254,6 +255,9 @@ typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...);
254int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 255int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
255 hpp_field_fn get_field, const char *fmt, 256 hpp_field_fn get_field, const char *fmt,
256 hpp_snprint_fn print_fn, bool fmt_percent); 257 hpp_snprint_fn print_fn, bool fmt_percent);
258int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he,
259 hpp_field_fn get_field, const char *fmt,
260 hpp_snprint_fn print_fn, bool fmt_percent);
257 261
258static inline void advance_hpp(struct perf_hpp *hpp, int inc) 262static inline void advance_hpp(struct perf_hpp *hpp, int inc)
259{ 263{
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 901b9bece2ee..9da8931d2394 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1061,6 +1061,7 @@ static struct hpp_dimension hpp_sort_dimensions[] = {
1061 DIM(PERF_HPP__OVERHEAD_US, "overhead_us"), 1061 DIM(PERF_HPP__OVERHEAD_US, "overhead_us"),
1062 DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"), 1062 DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"),
1063 DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"), 1063 DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"),
1064 DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"),
1064 DIM(PERF_HPP__SAMPLES, "sample"), 1065 DIM(PERF_HPP__SAMPLES, "sample"),
1065 DIM(PERF_HPP__PERIOD, "period"), 1066 DIM(PERF_HPP__PERIOD, "period"),
1066}; 1067};