aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/ui/hist.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/ui/hist.c')
-rw-r--r--tools/perf/ui/hist.c258
1 files changed, 15 insertions, 243 deletions
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 4bf91b09d62d..0a193281eba8 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -1,4 +1,5 @@
1#include <math.h> 1#include <math.h>
2#include <linux/compiler.h>
2 3
3#include "../util/hist.h" 4#include "../util/hist.h"
4#include "../util/util.h" 5#include "../util/util.h"
@@ -79,7 +80,8 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
79} 80}
80 81
81#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 82#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
82static int hpp__header_##_type(struct perf_hpp *hpp) \ 83static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
84 struct perf_hpp *hpp) \
83{ \ 85{ \
84 int len = _min_width; \ 86 int len = _min_width; \
85 \ 87 \
@@ -92,7 +94,8 @@ static int hpp__header_##_type(struct perf_hpp *hpp) \
92} 94}
93 95
94#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ 96#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \
95static int hpp__width_##_type(struct perf_hpp *hpp __maybe_unused) \ 97static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
98 struct perf_hpp *hpp __maybe_unused) \
96{ \ 99{ \
97 int len = _min_width; \ 100 int len = _min_width; \
98 \ 101 \
@@ -110,14 +113,16 @@ static u64 he_get_##_field(struct hist_entry *he) \
110 return he->stat._field; \ 113 return he->stat._field; \
111} \ 114} \
112 \ 115 \
113static int hpp__color_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ 116static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
117 struct perf_hpp *hpp, struct hist_entry *he) \
114{ \ 118{ \
115 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 119 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \
116 (hpp_snprint_fn)percent_color_snprintf, true); \ 120 (hpp_snprint_fn)percent_color_snprintf, true); \
117} 121}
118 122
119#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 123#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
120static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ 124static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \
125 struct perf_hpp *hpp, struct hist_entry *he) \
121{ \ 126{ \
122 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 127 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \
123 return __hpp__fmt(hpp, he, he_get_##_field, fmt, \ 128 return __hpp__fmt(hpp, he, he_get_##_field, fmt, \
@@ -130,7 +135,8 @@ static u64 he_get_raw_##_field(struct hist_entry *he) \
130 return he->stat._field; \ 135 return he->stat._field; \
131} \ 136} \
132 \ 137 \
133static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ 138static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \
139 struct perf_hpp *hpp, struct hist_entry *he) \
134{ \ 140{ \
135 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ 141 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \
136 return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf, false); \ 142 return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf, false); \
@@ -157,196 +163,6 @@ HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
157HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) 163HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12)
158HPP_RAW_FNS(period, "Period", period, 12, 12) 164HPP_RAW_FNS(period, "Period", period, 12, 12)
159 165
160
161static int hpp__header_baseline(struct perf_hpp *hpp)
162{
163 return scnprintf(hpp->buf, hpp->size, "Baseline");
164}
165
166static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
167{
168 return 8;
169}
170
171static double baseline_percent(struct hist_entry *he)
172{
173 struct hist_entry *pair = hist_entry__next_pair(he);
174 struct hists *pair_hists = pair ? pair->hists : NULL;
175 double percent = 0.0;
176
177 if (pair) {
178 u64 total_period = pair_hists->stats.total_period;
179 u64 base_period = pair->stat.period;
180
181 percent = 100.0 * base_period / total_period;
182 }
183
184 return percent;
185}
186
187static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
188{
189 double percent = baseline_percent(he);
190
191 if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
192 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
193 else
194 return scnprintf(hpp->buf, hpp->size, " ");
195}
196
197static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
198{
199 double percent = baseline_percent(he);
200 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
201
202 if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
203 return scnprintf(hpp->buf, hpp->size, fmt, percent);
204 else
205 return scnprintf(hpp->buf, hpp->size, " ");
206}
207
208static int hpp__header_period_baseline(struct perf_hpp *hpp)
209{
210 const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
211
212 return scnprintf(hpp->buf, hpp->size, fmt, "Period Base");
213}
214
215static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused)
216{
217 return 12;
218}
219
220static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he)
221{
222 struct hist_entry *pair = hist_entry__next_pair(he);
223 u64 period = pair ? pair->stat.period : 0;
224 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
225
226 return scnprintf(hpp->buf, hpp->size, fmt, period);
227}
228
229static int hpp__header_delta(struct perf_hpp *hpp)
230{
231 const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
232
233 return scnprintf(hpp->buf, hpp->size, fmt, "Delta");
234}
235
236static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
237{
238 return 7;
239}
240
241static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
242{
243 struct hist_entry *pair = hist_entry__next_pair(he);
244 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
245 char buf[32] = " ";
246 double diff = 0.0;
247
248 if (pair) {
249 if (he->diff.computed)
250 diff = he->diff.period_ratio_delta;
251 else
252 diff = perf_diff__compute_delta(he, pair);
253 } else
254 diff = perf_diff__period_percent(he, he->stat.period);
255
256 if (fabs(diff) >= 0.01)
257 scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
258
259 return scnprintf(hpp->buf, hpp->size, fmt, buf);
260}
261
262static int hpp__header_ratio(struct perf_hpp *hpp)
263{
264 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
265
266 return scnprintf(hpp->buf, hpp->size, fmt, "Ratio");
267}
268
269static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)
270{
271 return 14;
272}
273
274static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
275{
276 struct hist_entry *pair = hist_entry__next_pair(he);
277 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
278 char buf[32] = " ";
279 double ratio = 0.0;
280
281 if (pair) {
282 if (he->diff.computed)
283 ratio = he->diff.period_ratio;
284 else
285 ratio = perf_diff__compute_ratio(he, pair);
286 }
287
288 if (ratio > 0.0)
289 scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
290
291 return scnprintf(hpp->buf, hpp->size, fmt, buf);
292}
293
294static int hpp__header_wdiff(struct perf_hpp *hpp)
295{
296 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
297
298 return scnprintf(hpp->buf, hpp->size, fmt, "Weighted diff");
299}
300
301static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)
302{
303 return 14;
304}
305
306static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
307{
308 struct hist_entry *pair = hist_entry__next_pair(he);
309 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
310 char buf[32] = " ";
311 s64 wdiff = 0;
312
313 if (pair) {
314 if (he->diff.computed)
315 wdiff = he->diff.wdiff;
316 else
317 wdiff = perf_diff__compute_wdiff(he, pair);
318 }
319
320 if (wdiff != 0)
321 scnprintf(buf, sizeof(buf), "%14ld", wdiff);
322
323 return scnprintf(hpp->buf, hpp->size, fmt, buf);
324}
325
326static int hpp__header_formula(struct perf_hpp *hpp)
327{
328 const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
329
330 return scnprintf(hpp->buf, hpp->size, fmt, "Formula");
331}
332
333static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)
334{
335 return 70;
336}
337
338static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
339{
340 struct hist_entry *pair = hist_entry__next_pair(he);
341 const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
342 char buf[96] = " ";
343
344 if (pair)
345 perf_diff__formula(he, pair, buf, sizeof(buf));
346
347 return scnprintf(hpp->buf, hpp->size, fmt, buf);
348}
349
350#define HPP__COLOR_PRINT_FNS(_name) \ 166#define HPP__COLOR_PRINT_FNS(_name) \
351 { \ 167 { \
352 .header = hpp__header_ ## _name, \ 168 .header = hpp__header_ ## _name, \
@@ -363,19 +179,13 @@ static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
363 } 179 }
364 180
365struct perf_hpp_fmt perf_hpp__format[] = { 181struct perf_hpp_fmt perf_hpp__format[] = {
366 HPP__COLOR_PRINT_FNS(baseline),
367 HPP__COLOR_PRINT_FNS(overhead), 182 HPP__COLOR_PRINT_FNS(overhead),
368 HPP__COLOR_PRINT_FNS(overhead_sys), 183 HPP__COLOR_PRINT_FNS(overhead_sys),
369 HPP__COLOR_PRINT_FNS(overhead_us), 184 HPP__COLOR_PRINT_FNS(overhead_us),
370 HPP__COLOR_PRINT_FNS(overhead_guest_sys), 185 HPP__COLOR_PRINT_FNS(overhead_guest_sys),
371 HPP__COLOR_PRINT_FNS(overhead_guest_us), 186 HPP__COLOR_PRINT_FNS(overhead_guest_us),
372 HPP__PRINT_FNS(samples), 187 HPP__PRINT_FNS(samples),
373 HPP__PRINT_FNS(period), 188 HPP__PRINT_FNS(period)
374 HPP__PRINT_FNS(period_baseline),
375 HPP__PRINT_FNS(delta),
376 HPP__PRINT_FNS(ratio),
377 HPP__PRINT_FNS(wdiff),
378 HPP__PRINT_FNS(formula)
379}; 189};
380 190
381LIST_HEAD(perf_hpp__list); 191LIST_HEAD(perf_hpp__list);
@@ -396,6 +206,8 @@ LIST_HEAD(perf_hpp__list);
396 206
397void perf_hpp__init(void) 207void perf_hpp__init(void)
398{ 208{
209 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
210
399 if (symbol_conf.show_cpu_utilization) { 211 if (symbol_conf.show_cpu_utilization) {
400 perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS); 212 perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS);
401 perf_hpp__column_enable(PERF_HPP__OVERHEAD_US); 213 perf_hpp__column_enable(PERF_HPP__OVERHEAD_US);
@@ -424,46 +236,6 @@ void perf_hpp__column_enable(unsigned col)
424 perf_hpp__column_register(&perf_hpp__format[col]); 236 perf_hpp__column_register(&perf_hpp__format[col]);
425} 237}
426 238
427static inline void advance_hpp(struct perf_hpp *hpp, int inc)
428{
429 hpp->buf += inc;
430 hpp->size -= inc;
431}
432
433int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
434 bool color)
435{
436 const char *sep = symbol_conf.field_sep;
437 struct perf_hpp_fmt *fmt;
438 char *start = hpp->buf;
439 int ret;
440 bool first = true;
441
442 if (symbol_conf.exclude_other && !he->parent)
443 return 0;
444
445 perf_hpp__for_each_format(fmt) {
446 /*
447 * If there's no field_sep, we still need
448 * to display initial ' '.
449 */
450 if (!sep || !first) {
451 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
452 advance_hpp(hpp, ret);
453 } else
454 first = false;
455
456 if (color && fmt->color)
457 ret = fmt->color(hpp, he);
458 else
459 ret = fmt->entry(hpp, he);
460
461 advance_hpp(hpp, ret);
462 }
463
464 return hpp->buf - start;
465}
466
467int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size, 239int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
468 struct hists *hists) 240 struct hists *hists)
469{ 241{
@@ -499,7 +271,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
499 if (i) 271 if (i)
500 ret += 2; 272 ret += 2;
501 273
502 ret += fmt->width(&dummy_hpp); 274 ret += fmt->width(fmt, &dummy_hpp);
503 } 275 }
504 276
505 list_for_each_entry(se, &hist_entry__sort_list, list) 277 list_for_each_entry(se, &hist_entry__sort_list, list)