3 #include "../util/hist.h"
4 #include "../util/util.h"
5 #include "../util/sort.h"
8 /* hist period print (hpp) functions */
9 static int hpp__header_overhead(struct perf_hpp
*hpp
)
11 return scnprintf(hpp
->buf
, hpp
->size
, "Overhead");
14 static int hpp__width_overhead(struct perf_hpp
*hpp __maybe_unused
)
19 static int hpp__color_overhead(struct perf_hpp
*hpp
, struct hist_entry
*he
)
21 struct hists
*hists
= he
->hists
;
22 double percent
= 100.0 * he
->stat
.period
/ hists
->stats
.total_period
;
24 return percent_color_snprintf(hpp
->buf
, hpp
->size
, " %6.2f%%", percent
);
27 static int hpp__entry_overhead(struct perf_hpp
*hpp
, struct hist_entry
*he
)
29 struct hists
*hists
= he
->hists
;
30 double percent
= 100.0 * he
->stat
.period
/ hists
->stats
.total_period
;
31 const char *fmt
= symbol_conf
.field_sep
? "%.2f" : " %6.2f%%";
33 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, percent
);
36 static int hpp__header_overhead_sys(struct perf_hpp
*hpp
)
38 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%7s";
40 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "sys");
43 static int hpp__width_overhead_sys(struct perf_hpp
*hpp __maybe_unused
)
48 static int hpp__color_overhead_sys(struct perf_hpp
*hpp
, struct hist_entry
*he
)
50 struct hists
*hists
= he
->hists
;
51 double percent
= 100.0 * he
->stat
.period_sys
/ hists
->stats
.total_period
;
53 return percent_color_snprintf(hpp
->buf
, hpp
->size
, "%6.2f%%", percent
);
56 static int hpp__entry_overhead_sys(struct perf_hpp
*hpp
, struct hist_entry
*he
)
58 struct hists
*hists
= he
->hists
;
59 double percent
= 100.0 * he
->stat
.period_sys
/ hists
->stats
.total_period
;
60 const char *fmt
= symbol_conf
.field_sep
? "%.2f" : "%6.2f%%";
62 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, percent
);
65 static int hpp__header_overhead_us(struct perf_hpp
*hpp
)
67 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%7s";
69 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "user");
72 static int hpp__width_overhead_us(struct perf_hpp
*hpp __maybe_unused
)
77 static int hpp__color_overhead_us(struct perf_hpp
*hpp
, struct hist_entry
*he
)
79 struct hists
*hists
= he
->hists
;
80 double percent
= 100.0 * he
->stat
.period_us
/ hists
->stats
.total_period
;
82 return percent_color_snprintf(hpp
->buf
, hpp
->size
, "%6.2f%%", percent
);
85 static int hpp__entry_overhead_us(struct perf_hpp
*hpp
, struct hist_entry
*he
)
87 struct hists
*hists
= he
->hists
;
88 double percent
= 100.0 * he
->stat
.period_us
/ hists
->stats
.total_period
;
89 const char *fmt
= symbol_conf
.field_sep
? "%.2f" : "%6.2f%%";
91 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, percent
);
94 static int hpp__header_overhead_guest_sys(struct perf_hpp
*hpp
)
96 return scnprintf(hpp
->buf
, hpp
->size
, "guest sys");
99 static int hpp__width_overhead_guest_sys(struct perf_hpp
*hpp __maybe_unused
)
104 static int hpp__color_overhead_guest_sys(struct perf_hpp
*hpp
,
105 struct hist_entry
*he
)
107 struct hists
*hists
= he
->hists
;
108 double percent
= 100.0 * he
->stat
.period_guest_sys
/ hists
->stats
.total_period
;
110 return percent_color_snprintf(hpp
->buf
, hpp
->size
, " %6.2f%% ", percent
);
113 static int hpp__entry_overhead_guest_sys(struct perf_hpp
*hpp
,
114 struct hist_entry
*he
)
116 struct hists
*hists
= he
->hists
;
117 double percent
= 100.0 * he
->stat
.period_guest_sys
/ hists
->stats
.total_period
;
118 const char *fmt
= symbol_conf
.field_sep
? "%.2f" : " %6.2f%% ";
120 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, percent
);
123 static int hpp__header_overhead_guest_us(struct perf_hpp
*hpp
)
125 return scnprintf(hpp
->buf
, hpp
->size
, "guest usr");
128 static int hpp__width_overhead_guest_us(struct perf_hpp
*hpp __maybe_unused
)
133 static int hpp__color_overhead_guest_us(struct perf_hpp
*hpp
,
134 struct hist_entry
*he
)
136 struct hists
*hists
= he
->hists
;
137 double percent
= 100.0 * he
->stat
.period_guest_us
/ hists
->stats
.total_period
;
139 return percent_color_snprintf(hpp
->buf
, hpp
->size
, " %6.2f%% ", percent
);
142 static int hpp__entry_overhead_guest_us(struct perf_hpp
*hpp
,
143 struct hist_entry
*he
)
145 struct hists
*hists
= he
->hists
;
146 double percent
= 100.0 * he
->stat
.period_guest_us
/ hists
->stats
.total_period
;
147 const char *fmt
= symbol_conf
.field_sep
? "%.2f" : " %6.2f%% ";
149 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, percent
);
152 static int hpp__header_baseline(struct perf_hpp
*hpp
)
154 return scnprintf(hpp
->buf
, hpp
->size
, "Baseline");
157 static int hpp__width_baseline(struct perf_hpp
*hpp __maybe_unused
)
162 static double baseline_percent(struct hist_entry
*he
)
164 struct hist_entry
*pair
= hist_entry__next_pair(he
);
165 struct hists
*pair_hists
= pair
? pair
->hists
: NULL
;
166 double percent
= 0.0;
169 u64 total_period
= pair_hists
->stats
.total_period
;
170 u64 base_period
= pair
->stat
.period
;
172 percent
= 100.0 * base_period
/ total_period
;
178 static int hpp__color_baseline(struct perf_hpp
*hpp
, struct hist_entry
*he
)
180 double percent
= baseline_percent(he
);
182 if (hist_entry__has_pairs(he
))
183 return percent_color_snprintf(hpp
->buf
, hpp
->size
, " %6.2f%%", percent
);
185 return scnprintf(hpp
->buf
, hpp
->size
, " ");
188 static int hpp__entry_baseline(struct perf_hpp
*hpp
, struct hist_entry
*he
)
190 double percent
= baseline_percent(he
);
191 const char *fmt
= symbol_conf
.field_sep
? "%.2f" : " %6.2f%%";
193 if (hist_entry__has_pairs(he
) || symbol_conf
.field_sep
)
194 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, percent
);
196 return scnprintf(hpp
->buf
, hpp
->size
, " ");
199 static int hpp__header_samples(struct perf_hpp
*hpp
)
201 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%11s";
203 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "Samples");
206 static int hpp__width_samples(struct perf_hpp
*hpp __maybe_unused
)
211 static int hpp__entry_samples(struct perf_hpp
*hpp
, struct hist_entry
*he
)
213 const char *fmt
= symbol_conf
.field_sep
? "%" PRIu64
: "%11" PRIu64
;
215 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, he
->stat
.nr_events
);
218 static int hpp__header_period(struct perf_hpp
*hpp
)
220 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%12s";
222 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "Period");
225 static int hpp__width_period(struct perf_hpp
*hpp __maybe_unused
)
230 static int hpp__entry_period(struct perf_hpp
*hpp
, struct hist_entry
*he
)
232 const char *fmt
= symbol_conf
.field_sep
? "%" PRIu64
: "%12" PRIu64
;
234 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, he
->stat
.period
);
237 static int hpp__header_period_baseline(struct perf_hpp
*hpp
)
239 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%12s";
241 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "Period Base");
244 static int hpp__width_period_baseline(struct perf_hpp
*hpp __maybe_unused
)
249 static int hpp__entry_period_baseline(struct perf_hpp
*hpp
, struct hist_entry
*he
)
251 struct hist_entry
*pair
= hist_entry__next_pair(he
);
252 u64 period
= pair
? pair
->stat
.period
: 0;
253 const char *fmt
= symbol_conf
.field_sep
? "%" PRIu64
: "%12" PRIu64
;
255 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, period
);
257 static int hpp__header_delta(struct perf_hpp
*hpp
)
259 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%7s";
261 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "Delta");
264 static int hpp__width_delta(struct perf_hpp
*hpp __maybe_unused
)
269 static int hpp__entry_delta(struct perf_hpp
*hpp
, struct hist_entry
*he
)
271 struct hist_entry
*pair
= hist_entry__next_pair(he
);
272 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%7.7s";
277 if (he
->diff
.computed
)
278 diff
= he
->diff
.period_ratio_delta
;
280 diff
= perf_diff__compute_delta(he
, pair
);
282 diff
= perf_diff__period_percent(he
, he
->stat
.period
);
284 if (fabs(diff
) >= 0.01)
285 scnprintf(buf
, sizeof(buf
), "%+4.2F%%", diff
);
287 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, buf
);
290 static int hpp__header_ratio(struct perf_hpp
*hpp
)
292 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%14s";
294 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "Ratio");
297 static int hpp__width_ratio(struct perf_hpp
*hpp __maybe_unused
)
302 static int hpp__entry_ratio(struct perf_hpp
*hpp
, struct hist_entry
*he
)
304 struct hist_entry
*pair
= hist_entry__next_pair(he
);
305 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%14s";
310 if (he
->diff
.computed
)
311 ratio
= he
->diff
.period_ratio
;
313 ratio
= perf_diff__compute_ratio(he
, pair
);
317 scnprintf(buf
, sizeof(buf
), "%+14.6F", ratio
);
319 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, buf
);
322 static int hpp__header_wdiff(struct perf_hpp
*hpp
)
324 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%14s";
326 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "Weighted diff");
329 static int hpp__width_wdiff(struct perf_hpp
*hpp __maybe_unused
)
334 static int hpp__entry_wdiff(struct perf_hpp
*hpp
, struct hist_entry
*he
)
336 struct hist_entry
*pair
= hist_entry__next_pair(he
);
337 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%14s";
342 if (he
->diff
.computed
)
343 wdiff
= he
->diff
.wdiff
;
345 wdiff
= perf_diff__compute_wdiff(he
, pair
);
349 scnprintf(buf
, sizeof(buf
), "%14ld", wdiff
);
351 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, buf
);
354 static int hpp__header_displ(struct perf_hpp
*hpp
)
356 return scnprintf(hpp
->buf
, hpp
->size
, "Displ.");
359 static int hpp__width_displ(struct perf_hpp
*hpp __maybe_unused
)
364 static int hpp__entry_displ(struct perf_hpp
*hpp
,
365 struct hist_entry
*he
)
367 struct hist_entry
*pair
= hist_entry__next_pair(he
);
368 long displacement
= pair
? pair
->position
- he
->position
: 0;
369 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%6.6s";
373 scnprintf(buf
, sizeof(buf
), "%+4ld", displacement
);
375 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, buf
);
378 static int hpp__header_formula(struct perf_hpp
*hpp
)
380 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%70s";
382 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, "Formula");
385 static int hpp__width_formula(struct perf_hpp
*hpp __maybe_unused
)
390 static int hpp__entry_formula(struct perf_hpp
*hpp
, struct hist_entry
*he
)
392 const char *fmt
= symbol_conf
.field_sep
? "%s" : "%-70s";
395 perf_diff__formula(buf
, sizeof(buf
), he
);
396 return scnprintf(hpp
->buf
, hpp
->size
, fmt
, buf
);
399 #define HPP__COLOR_PRINT_FNS(_name) \
401 .header = hpp__header_ ## _name, \
402 .width = hpp__width_ ## _name, \
403 .color = hpp__color_ ## _name, \
404 .entry = hpp__entry_ ## _name \
407 #define HPP__PRINT_FNS(_name) \
409 .header = hpp__header_ ## _name, \
410 .width = hpp__width_ ## _name, \
411 .entry = hpp__entry_ ## _name \
414 struct perf_hpp_fmt perf_hpp__format
[] = {
415 HPP__COLOR_PRINT_FNS(baseline
),
416 HPP__COLOR_PRINT_FNS(overhead
),
417 HPP__COLOR_PRINT_FNS(overhead_sys
),
418 HPP__COLOR_PRINT_FNS(overhead_us
),
419 HPP__COLOR_PRINT_FNS(overhead_guest_sys
),
420 HPP__COLOR_PRINT_FNS(overhead_guest_us
),
421 HPP__PRINT_FNS(samples
),
422 HPP__PRINT_FNS(period
),
423 HPP__PRINT_FNS(period_baseline
),
424 HPP__PRINT_FNS(delta
),
425 HPP__PRINT_FNS(ratio
),
426 HPP__PRINT_FNS(wdiff
),
427 HPP__PRINT_FNS(displ
),
428 HPP__PRINT_FNS(formula
)
431 LIST_HEAD(perf_hpp__list
);
433 #undef HPP__COLOR_PRINT_FNS
434 #undef HPP__PRINT_FNS
436 void perf_hpp__init(void)
438 if (symbol_conf
.show_cpu_utilization
) {
439 perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS
);
440 perf_hpp__column_enable(PERF_HPP__OVERHEAD_US
);
443 perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_SYS
);
444 perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_US
);
448 if (symbol_conf
.show_nr_samples
)
449 perf_hpp__column_enable(PERF_HPP__SAMPLES
);
451 if (symbol_conf
.show_total_period
)
452 perf_hpp__column_enable(PERF_HPP__PERIOD
);
455 void perf_hpp__column_register(struct perf_hpp_fmt
*format
)
457 list_add_tail(&format
->list
, &perf_hpp__list
);
460 void perf_hpp__column_enable(unsigned col
)
462 BUG_ON(col
>= PERF_HPP__MAX_INDEX
);
463 perf_hpp__column_register(&perf_hpp__format
[col
]);
466 static inline void advance_hpp(struct perf_hpp
*hpp
, int inc
)
472 int hist_entry__period_snprintf(struct perf_hpp
*hpp
, struct hist_entry
*he
,
475 const char *sep
= symbol_conf
.field_sep
;
476 struct perf_hpp_fmt
*fmt
;
477 char *start
= hpp
->buf
;
481 if (symbol_conf
.exclude_other
&& !he
->parent
)
484 perf_hpp__for_each_format(fmt
) {
486 * If there's no field_sep, we still need
487 * to display initial ' '.
489 if (!sep
|| !first
) {
490 ret
= scnprintf(hpp
->buf
, hpp
->size
, "%s", sep
?: " ");
491 advance_hpp(hpp
, ret
);
495 if (color
&& fmt
->color
)
496 ret
= fmt
->color(hpp
, he
);
498 ret
= fmt
->entry(hpp
, he
);
500 advance_hpp(hpp
, ret
);
503 return hpp
->buf
- start
;
506 int hist_entry__sort_snprintf(struct hist_entry
*he
, char *s
, size_t size
,
509 const char *sep
= symbol_conf
.field_sep
;
510 struct sort_entry
*se
;
513 list_for_each_entry(se
, &hist_entry__sort_list
, list
) {
517 ret
+= scnprintf(s
+ ret
, size
- ret
, "%s", sep
?: " ");
518 ret
+= se
->se_snprintf(he
, s
+ ret
, size
- ret
,
519 hists__col_len(hists
, se
->se_width_idx
));
526 * See hists__fprintf to match the column widths
528 unsigned int hists__sort_list_width(struct hists
*hists
)
530 struct perf_hpp_fmt
*fmt
;
531 struct sort_entry
*se
;
534 perf_hpp__for_each_format(fmt
) {
538 ret
+= fmt
->width(NULL
);
541 list_for_each_entry(se
, &hist_entry__sort_list
, list
)
543 ret
+= 2 + hists__col_len(hists
, se
->se_width_idx
);
545 if (verbose
) /* Addr + origin */
546 ret
+= 3 + BITS_PER_LONG
/ 4;