aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung.kim@lge.com>2012-09-02 22:53:06 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-09-08 12:19:44 -0400
commitea251d51d2c7d7233790123227f787c477f567f5 (patch)
treeedc255462a434ecd3bbb1fac16daf1198a050e2e
parent8bf98b89688c3d7ec071bf26d49761e38d846b47 (diff)
perf hists: Introduce perf_hpp for hist period printing
Current hist print functions are messy because it has to consider many of command line options and the code doing that is scattered around to places. So when someone wants to add an option to manipulate the hist output it'd very easy to miss to update all of them in sync. And things getting worse as more options/features are added continuously. So I'd like to refactor them using hpp formats and move common code to ui/hist.c in order to make it easy to maintain and to add new features. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1346640790-17197-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-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