aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/builtin-diff.c1
-rw-r--r--tools/perf/ui/hist.c340
-rw-r--r--tools/perf/ui/setup.c8
-rw-r--r--tools/perf/ui/stdio/hist.c238
-rw-r--r--tools/perf/util/hist.h37
6 files changed, 426 insertions, 200 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 3eda49215730..e4b2e8f2606c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -403,7 +403,9 @@ LIB_OBJS += $(OUTPUT)util/cgroup.o
403LIB_OBJS += $(OUTPUT)util/target.o 403LIB_OBJS += $(OUTPUT)util/target.o
404LIB_OBJS += $(OUTPUT)util/rblist.o 404LIB_OBJS += $(OUTPUT)util/rblist.o
405LIB_OBJS += $(OUTPUT)util/intlist.o 405LIB_OBJS += $(OUTPUT)util/intlist.o
406
406LIB_OBJS += $(OUTPUT)ui/helpline.o 407LIB_OBJS += $(OUTPUT)ui/helpline.o
408LIB_OBJS += $(OUTPUT)ui/hist.o
407LIB_OBJS += $(OUTPUT)ui/stdio/hist.o 409LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
408 410
409BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 411BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index e9933fdd256e..c4c6d76b70ea 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -264,6 +264,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __used)
264 if (symbol__init() < 0) 264 if (symbol__init() < 0)
265 return -1; 265 return -1;
266 266
267 perf_hpp__init(true, show_displacement);
267 setup_sorting(diff_usage, options); 268 setup_sorting(diff_usage, options);
268 setup_pager(); 269 setup_pager();
269 270
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
new file mode 100644
index 000000000000..8ccd1f2330d1
--- /dev/null
+++ b/tools/perf/ui/hist.c
@@ -0,0 +1,340 @@
1#include <math.h>
2
3#include "../util/hist.h"
4#include "../util/util.h"
5#include "../util/sort.h"
6
7
8/* hist period print (hpp) functions */
9static int hpp__header_overhead(struct perf_hpp *hpp)
10{
11 if (hpp->ptr)
12 return scnprintf(hpp->buf, hpp->size, "Baseline");
13 else
14 return scnprintf(hpp->buf, hpp->size, "Overhead");
15}
16
17static int hpp__width_overhead(struct perf_hpp *hpp __used)
18{
19 return 8;
20}
21
22static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
23{
24 double percent = 100.0 * he->period / hpp->total_period;
25
26 if (hpp->ptr) {
27 struct hists *old_hists = hpp->ptr;
28 u64 total_period = old_hists->stats.total_period;
29 u64 base_period = he->pair ? he->pair->period : 0;
30
31 if (total_period)
32 percent = 100.0 * base_period / total_period;
33 else
34 percent = 0.0;
35 }
36
37 return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%%", percent);
38}
39
40static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
41{
42 double percent = 100.0 * he->period / hpp->total_period;
43
44 if (hpp->ptr) {
45 struct hists *old_hists = hpp->ptr;
46 u64 total_period = old_hists->stats.total_period;
47 u64 base_period = he->pair ? he->pair->period : 0;
48
49 if (total_period)
50 percent = 100.0 * base_period / total_period;
51 else
52 percent = 0.0;
53 }
54
55 return scnprintf(hpp->buf, hpp->size, " %5.2f%%", percent);
56}
57
58static int hpp__header_overhead_sys(struct perf_hpp *hpp)
59{
60 return scnprintf(hpp->buf, hpp->size, " sys ");
61}
62
63static int hpp__width_overhead_sys(struct perf_hpp *hpp __used)
64{
65 return 6;
66}
67
68static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
69{
70 double percent = 100.0 * he->period_sys / hpp->total_period;
71 return percent_color_snprintf(hpp->buf, hpp->size, "%5.2f%%", percent);
72}
73
74static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
75{
76 double percent = 100.0 * he->period_sys / hpp->total_period;
77 return scnprintf(hpp->buf, hpp->size, "%5.2f%%", percent);
78}
79
80static int hpp__header_overhead_us(struct perf_hpp *hpp)
81{
82 return scnprintf(hpp->buf, hpp->size, " user ");
83}
84
85static int hpp__width_overhead_us(struct perf_hpp *hpp __used)
86{
87 return 6;
88}
89
90static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
91{
92 double percent = 100.0 * he->period_us / hpp->total_period;
93 return percent_color_snprintf(hpp->buf, hpp->size, "%5.2f%%", percent);
94}
95
96static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
97{
98 double percent = 100.0 * he->period_us / hpp->total_period;
99 return scnprintf(hpp->buf, hpp->size, "%5.2f%%", percent);
100}
101
102static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
103{
104 return scnprintf(hpp->buf, hpp->size, "guest sys");
105}
106
107static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __used)
108{
109 return 9;
110}
111
112static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
113 struct hist_entry *he)
114{
115 double percent = 100.0 * he->period_guest_sys / hpp->total_period;
116 return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%% ", percent);
117}
118
119static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
120 struct hist_entry *he)
121{
122 double percent = 100.0 * he->period_guest_sys / hpp->total_period;
123 return scnprintf(hpp->buf, hpp->size, " %5.2f%% ", percent);
124}
125
126static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
127{
128 return scnprintf(hpp->buf, hpp->size, "guest usr");
129}
130
131static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __used)
132{
133 return 9;
134}
135
136static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
137 struct hist_entry *he)
138{
139 double percent = 100.0 * he->period_guest_us / hpp->total_period;
140 return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%% ", percent);
141}
142
143static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
144 struct hist_entry *he)
145{
146 double percent = 100.0 * he->period_guest_us / hpp->total_period;
147 return scnprintf(hpp->buf, hpp->size, " %5.2f%% ", percent);
148}
149
150static int hpp__header_samples(struct perf_hpp *hpp)
151{
152 return scnprintf(hpp->buf, hpp->size, " Samples ");
153}
154
155static int hpp__width_samples(struct perf_hpp *hpp __used)
156{
157 return 11;
158}
159
160static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
161{
162 return scnprintf(hpp->buf, hpp->size, "%11" PRIu64, he->nr_events);
163}
164
165static int hpp__header_period(struct perf_hpp *hpp)
166{
167 return scnprintf(hpp->buf, hpp->size, " Period ");
168}
169
170static int hpp__width_period(struct perf_hpp *hpp __used)
171{
172 return 12;
173}
174
175static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
176{
177 return scnprintf(hpp->buf, hpp->size, "%12" PRIu64, he->period);
178}
179
180static int hpp__header_delta(struct perf_hpp *hpp)
181{
182 return scnprintf(hpp->buf, hpp->size, " Delta ");
183}
184
185static int hpp__width_delta(struct perf_hpp *hpp __used)
186{
187 return 7;
188}
189
190static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
191{
192 struct hists *pair_hists = hpp->ptr;
193 u64 old_total, new_total;
194 double old_percent = 0, new_percent = 0;
195 double diff;
196 char buf[32];
197
198 old_total = pair_hists->stats.total_period;
199 if (old_total > 0 && he->pair)
200 old_percent = 100.0 * he->pair->period / old_total;
201
202 new_total = hpp->total_period;
203 if (new_total > 0)
204 new_percent = 100.0 * he->period / new_total;
205
206 diff = new_percent - old_percent;
207 if (fabs(diff) < 0.01)
208 return scnprintf(hpp->buf, hpp->size, " ");
209
210 scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
211 return scnprintf(hpp->buf, hpp->size, "%7.7s", buf);
212}
213
214static int hpp__header_displ(struct perf_hpp *hpp)
215{
216 return scnprintf(hpp->buf, hpp->size, "Displ.");
217}
218
219static int hpp__width_displ(struct perf_hpp *hpp __used)
220{
221 return 6;
222}
223
224static int hpp__entry_displ(struct perf_hpp *hpp, struct hist_entry *he __used)
225{
226 char buf[32];
227
228 if (!hpp->displacement)
229 return scnprintf(hpp->buf, hpp->size, " ");
230
231 scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement);
232 return scnprintf(hpp->buf, hpp->size, "%6.6s", buf);
233}
234
235#define HPP__COLOR_PRINT_FNS(_name) \
236 .header = hpp__header_ ## _name, \
237 .width = hpp__width_ ## _name, \
238 .color = hpp__color_ ## _name, \
239 .entry = hpp__entry_ ## _name
240
241#define HPP__PRINT_FNS(_name) \
242 .header = hpp__header_ ## _name, \
243 .width = hpp__width_ ## _name, \
244 .entry = hpp__entry_ ## _name
245
246struct perf_hpp_fmt perf_hpp__format[] = {
247 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
248 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
249 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
250 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) },
251 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
252 { .cond = false, HPP__PRINT_FNS(samples) },
253 { .cond = false, HPP__PRINT_FNS(period) },
254 { .cond = false, HPP__PRINT_FNS(delta) },
255 { .cond = false, HPP__PRINT_FNS(displ) }
256};
257
258#undef HPP__COLOR_PRINT_FNS
259#undef HPP__PRINT_FNS
260
261void perf_hpp__init(bool need_pair, bool show_displacement)
262{
263 if (symbol_conf.show_cpu_utilization) {
264 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
265 perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true;
266
267 if (perf_guest) {
268 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true;
269 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true;
270 }
271 }
272
273 if (symbol_conf.show_nr_samples)
274 perf_hpp__format[PERF_HPP__SAMPLES].cond = true;
275
276 if (symbol_conf.show_total_period)
277 perf_hpp__format[PERF_HPP__PERIOD].cond = true;
278
279 if (need_pair) {
280 perf_hpp__format[PERF_HPP__DELTA].cond = true;
281
282 if (show_displacement)
283 perf_hpp__format[PERF_HPP__DISPL].cond = true;
284 }
285}
286
287static inline void advance_hpp(struct perf_hpp *hpp, int inc)
288{
289 hpp->buf += inc;
290 hpp->size -= inc;
291}
292
293int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
294 bool color)
295{
296 const char *sep = symbol_conf.field_sep;
297 char *start = hpp->buf;
298 int i, ret;
299
300 if (symbol_conf.exclude_other && !he->parent)
301 return 0;
302
303 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
304 if (!perf_hpp__format[i].cond)
305 continue;
306
307 if (!sep || i > 0) {
308 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
309 advance_hpp(hpp, ret);
310 }
311
312 if (color && perf_hpp__format[i].color)
313 ret = perf_hpp__format[i].color(hpp, he);
314 else
315 ret = perf_hpp__format[i].entry(hpp, he);
316
317 advance_hpp(hpp, ret);
318 }
319
320 return hpp->buf - start;
321}
322
323int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
324 struct hists *hists)
325{
326 const char *sep = symbol_conf.field_sep;
327 struct sort_entry *se;
328 int ret = 0;
329
330 list_for_each_entry(se, &hist_entry__sort_list, list) {
331 if (se->elide)
332 continue;
333
334 ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
335 ret += se->se_snprintf(he, s + ret, size - ret,
336 hists__col_len(hists, se->se_width_idx));
337 }
338
339 return ret;
340}
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index c7820e569660..bd7d460f844c 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -1,8 +1,8 @@
1#include <pthread.h> 1#include <pthread.h>
2 2
3#include "../cache.h" 3#include "../util/cache.h"
4#include "../debug.h" 4#include "../util/debug.h"
5 5#include "../util/hist.h"
6 6
7pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; 7pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
8 8
@@ -29,6 +29,8 @@ void setup_browser(bool fallback_to_pager)
29 use_browser = 0; 29 use_browser = 0;
30 if (fallback_to_pager) 30 if (fallback_to_pager)
31 setup_pager(); 31 setup_pager();
32
33 perf_hpp__init(false, false);
32 break; 34 break;
33 } 35 }
34} 36}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 9bf7e9e5a72e..4228b4c6b72d 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -1,5 +1,4 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <math.h>
3 2
4#include "../../util/util.h" 3#include "../../util/util.h"
5#include "../../util/hist.h" 4#include "../../util/hist.h"
@@ -291,138 +290,6 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
291 return 0; 290 return 0;
292} 291}
293 292
294static int hist_entry__period_snprintf(struct hist_entry *he, char *s,
295 size_t size, struct hists *pair_hists,
296 bool show_displacement, long displacement,
297 bool color, u64 total_period)
298{
299 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
300 u64 nr_events;
301 const char *sep = symbol_conf.field_sep;
302 int ret;
303
304 if (symbol_conf.exclude_other && !he->parent)
305 return 0;
306
307 if (pair_hists) {
308 period = he->pair ? he->pair->period : 0;
309 nr_events = he->pair ? he->pair->nr_events : 0;
310 total = pair_hists->stats.total_period;
311 period_sys = he->pair ? he->pair->period_sys : 0;
312 period_us = he->pair ? he->pair->period_us : 0;
313 period_guest_sys = he->pair ? he->pair->period_guest_sys : 0;
314 period_guest_us = he->pair ? he->pair->period_guest_us : 0;
315 } else {
316 period = he->period;
317 nr_events = he->nr_events;
318 total = total_period;
319 period_sys = he->period_sys;
320 period_us = he->period_us;
321 period_guest_sys = he->period_guest_sys;
322 period_guest_us = he->period_guest_us;
323 }
324
325 if (total) {
326 if (color)
327 ret = percent_color_snprintf(s, size,
328 sep ? "%.2f" : " %6.2f%%",
329 (period * 100.0) / total);
330 else
331 ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%",
332 (period * 100.0) / total);
333 if (symbol_conf.show_cpu_utilization) {
334 ret += percent_color_snprintf(s + ret, size - ret,
335 sep ? "%.2f" : " %6.2f%%",
336 (period_sys * 100.0) / total);
337 ret += percent_color_snprintf(s + ret, size - ret,
338 sep ? "%.2f" : " %6.2f%%",
339 (period_us * 100.0) / total);
340 if (perf_guest) {
341 ret += percent_color_snprintf(s + ret,
342 size - ret,
343 sep ? "%.2f" : " %6.2f%%",
344 (period_guest_sys * 100.0) /
345 total);
346 ret += percent_color_snprintf(s + ret,
347 size - ret,
348 sep ? "%.2f" : " %6.2f%%",
349 (period_guest_us * 100.0) /
350 total);
351 }
352 }
353 } else
354 ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
355
356 if (symbol_conf.show_nr_samples) {
357 if (sep)
358 ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
359 else
360 ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
361 }
362
363 if (symbol_conf.show_total_period) {
364 if (sep)
365 ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
366 else
367 ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period);
368 }
369
370 if (pair_hists) {
371 char bf[32];
372 double old_percent = 0, new_percent = 0, diff;
373
374 if (total > 0)
375 old_percent = (period * 100.0) / total;
376 if (total_period > 0)
377 new_percent = (he->period * 100.0) / total_period;
378
379 diff = new_percent - old_percent;
380
381 if (fabs(diff) >= 0.01)
382 scnprintf(bf, sizeof(bf), "%+4.2F%%", diff);
383 else
384 scnprintf(bf, sizeof(bf), " ");
385
386 if (sep)
387 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
388 else
389 ret += scnprintf(s + ret, size - ret, "%11.11s", bf);
390
391 if (show_displacement) {
392 if (displacement)
393 scnprintf(bf, sizeof(bf), "%+4ld", displacement);
394 else
395 scnprintf(bf, sizeof(bf), " ");
396
397 if (sep)
398 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
399 else
400 ret += scnprintf(s + ret, size - ret, "%6.6s", bf);
401 }
402 }
403
404 return ret;
405}
406
407int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
408 struct hists *hists)
409{
410 const char *sep = symbol_conf.field_sep;
411 struct sort_entry *se;
412 int ret = 0;
413
414 list_for_each_entry(se, &hist_entry__sort_list, list) {
415 if (se->elide)
416 continue;
417
418 ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
419 ret += se->se_snprintf(he, s + ret, size - ret,
420 hists__col_len(hists, se->se_width_idx));
421 }
422
423 return ret;
424}
425
426static size_t hist_entry__callchain_fprintf(struct hist_entry *he, 293static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
427 struct hists *hists, 294 struct hists *hists,
428 u64 total_period, FILE *fp) 295 u64 total_period, FILE *fp)
@@ -441,18 +308,22 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
441 308
442static int hist_entry__fprintf(struct hist_entry *he, size_t size, 309static int hist_entry__fprintf(struct hist_entry *he, size_t size,
443 struct hists *hists, struct hists *pair_hists, 310 struct hists *hists, struct hists *pair_hists,
444 bool show_displacement, long displacement, 311 long displacement, u64 total_period, FILE *fp)
445 u64 total_period, FILE *fp)
446{ 312{
447 char bf[512]; 313 char bf[512];
448 int ret; 314 int ret;
315 struct perf_hpp hpp = {
316 .buf = bf,
317 .size = size,
318 .total_period = total_period,
319 .displacement = displacement,
320 .ptr = pair_hists,
321 };
449 322
450 if (size == 0 || size > sizeof(bf)) 323 if (size == 0 || size > sizeof(bf))
451 size = sizeof(bf); 324 size = hpp.size = sizeof(bf);
452 325
453 ret = hist_entry__period_snprintf(he, bf, size, pair_hists, 326 ret = hist_entry__period_snprintf(&hpp, he, true);
454 show_displacement, displacement,
455 true, total_period);
456 hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); 327 hist_entry__sort_snprintf(he, bf + ret, size - ret, hists);
457 328
458 ret = fprintf(fp, "%s\n", bf); 329 ret = fprintf(fp, "%s\n", bf);
@@ -477,59 +348,29 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
477 unsigned int width; 348 unsigned int width;
478 const char *sep = symbol_conf.field_sep; 349 const char *sep = symbol_conf.field_sep;
479 const char *col_width = symbol_conf.col_width_list_str; 350 const char *col_width = symbol_conf.col_width_list_str;
480 int nr_rows = 0; 351 int idx, nr_rows = 0;
352 char bf[64];
353 struct perf_hpp dummy_hpp = {
354 .buf = bf,
355 .size = sizeof(bf),
356 .ptr = pair,
357 };
481 358
482 init_rem_hits(); 359 init_rem_hits();
483 360
484 if (!show_header) 361 if (!show_header)
485 goto print_entries; 362 goto print_entries;
486 363
487 fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); 364 fprintf(fp, "# ");
488 365 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
489 if (symbol_conf.show_cpu_utilization) { 366 if (!perf_hpp__format[idx].cond)
490 if (sep) { 367 continue;
491 ret += fprintf(fp, "%csys", *sep);
492 ret += fprintf(fp, "%cus", *sep);
493 if (perf_guest) {
494 ret += fprintf(fp, "%cguest sys", *sep);
495 ret += fprintf(fp, "%cguest us", *sep);
496 }
497 } else {
498 ret += fprintf(fp, " sys ");
499 ret += fprintf(fp, " us ");
500 if (perf_guest) {
501 ret += fprintf(fp, " guest sys ");
502 ret += fprintf(fp, " guest us ");
503 }
504 }
505 }
506
507 if (symbol_conf.show_nr_samples) {
508 if (sep)
509 fprintf(fp, "%cSamples", *sep);
510 else
511 fputs(" Samples ", fp);
512 }
513
514 if (symbol_conf.show_total_period) {
515 if (sep)
516 ret += fprintf(fp, "%cPeriod", *sep);
517 else
518 ret += fprintf(fp, " Period ");
519 }
520 368
521 if (pair) { 369 if (idx)
522 if (sep) 370 fprintf(fp, "%s", sep ?: " ");
523 ret += fprintf(fp, "%cDelta", *sep);
524 else
525 ret += fprintf(fp, " Delta ");
526 371
527 if (show_displacement) { 372 perf_hpp__format[idx].header(&dummy_hpp);
528 if (sep) 373 fprintf(fp, "%s", bf);
529 ret += fprintf(fp, "%cDisplacement", *sep);
530 else
531 ret += fprintf(fp, " Displ");
532 }
533 } 374 }
534 375
535 list_for_each_entry(se, &hist_entry__sort_list, list) { 376 list_for_each_entry(se, &hist_entry__sort_list, list) {
@@ -561,18 +402,21 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
561 if (sep) 402 if (sep)
562 goto print_entries; 403 goto print_entries;
563 404
564 fprintf(fp, "# ........"); 405 fprintf(fp, "# ");
565 if (symbol_conf.show_cpu_utilization) 406 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
566 fprintf(fp, " ....... ......."); 407 unsigned int i;
567 if (symbol_conf.show_nr_samples) 408
568 fprintf(fp, " .........."); 409 if (!perf_hpp__format[idx].cond)
569 if (symbol_conf.show_total_period) 410 continue;
570 fprintf(fp, " ............"); 411
571 if (pair) { 412 if (idx)
572 fprintf(fp, " .........."); 413 fprintf(fp, "%s", sep ?: " ");
573 if (show_displacement) 414
574 fprintf(fp, " ....."); 415 width = perf_hpp__format[idx].width(&dummy_hpp);
416 for (i = 0; i < width; i++)
417 fprintf(fp, ".");
575 } 418 }
419
576 list_for_each_entry(se, &hist_entry__sort_list, list) { 420 list_for_each_entry(se, &hist_entry__sort_list, list) {
577 unsigned int i; 421 unsigned int i;
578 422
@@ -612,8 +456,8 @@ print_entries:
612 displacement = 0; 456 displacement = 0;
613 ++position; 457 ++position;
614 } 458 }
615 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement, 459 ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement,
616 displacement, total_period, fp); 460 total_period, fp);
617 461
618 if (max_rows && ++nr_rows >= max_rows) 462 if (max_rows && ++nr_rows >= max_rows)
619 goto out; 463 goto out;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2e650ffb7d23..4146f51124f0 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -115,6 +115,43 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
115void hists__reset_col_len(struct hists *hists); 115void hists__reset_col_len(struct hists *hists);
116void hists__calc_col_len(struct hists *hists, struct hist_entry *he); 116void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
117 117
118struct perf_hpp {
119 char *buf;
120 size_t size;
121 u64 total_period;
122 const char *sep;
123 long displacement;
124 void *ptr;
125};
126
127struct perf_hpp_fmt {
128 bool cond;
129 int (*header)(struct perf_hpp *hpp);
130 int (*width)(struct perf_hpp *hpp);
131 int (*color)(struct perf_hpp *hpp, struct hist_entry *he);
132 int (*entry)(struct perf_hpp *hpp, struct hist_entry *he);
133};
134
135extern struct perf_hpp_fmt perf_hpp__format[];
136
137enum {
138 PERF_HPP__OVERHEAD,
139 PERF_HPP__OVERHEAD_SYS,
140 PERF_HPP__OVERHEAD_US,
141 PERF_HPP__OVERHEAD_GUEST_SYS,
142 PERF_HPP__OVERHEAD_GUEST_US,
143 PERF_HPP__SAMPLES,
144 PERF_HPP__PERIOD,
145 PERF_HPP__DELTA,
146 PERF_HPP__DISPL,
147
148 PERF_HPP__MAX_INDEX
149};
150
151void perf_hpp__init(bool need_pair, bool show_displacement);
152int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
153 bool color);
154
118struct perf_evlist; 155struct perf_evlist;
119 156
120#ifdef NO_NEWT_SUPPORT 157#ifdef NO_NEWT_SUPPORT