blob: e8853f7780a3782adc200a8dfe856e2bad3c3c36 [file] [log] [blame]
Namhyung Kimea251d52012-09-03 11:53:06 +09001#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{
Jiri Olsa5395a042012-10-04 21:49:37 +090011 return scnprintf(hpp->buf, hpp->size, "Overhead");
Namhyung Kimea251d52012-09-03 11:53:06 +090012}
13
Irina Tirdea1d037ca2012-09-11 01:15:03 +030014static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +090015{
16 return 8;
17}
18
19static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
20{
21 double percent = 100.0 * he->period / hpp->total_period;
22
Namhyung Kim721b3112012-09-12 15:35:05 +090023 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
Namhyung Kimea251d52012-09-03 11:53:06 +090024}
25
26static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
27{
28 double percent = 100.0 * he->period / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +090029 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
Namhyung Kimea251d52012-09-03 11:53:06 +090030
Namhyung Kim9ffad982012-09-03 11:53:07 +090031 return scnprintf(hpp->buf, hpp->size, fmt, percent);
Namhyung Kimea251d52012-09-03 11:53:06 +090032}
33
34static int hpp__header_overhead_sys(struct perf_hpp *hpp)
35{
Namhyung Kim721b3112012-09-12 15:35:05 +090036 const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
Namhyung Kim9ffad982012-09-03 11:53:07 +090037
38 return scnprintf(hpp->buf, hpp->size, fmt, "sys");
Namhyung Kimea251d52012-09-03 11:53:06 +090039}
40
Irina Tirdea1d037ca2012-09-11 01:15:03 +030041static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +090042{
Namhyung Kim721b3112012-09-12 15:35:05 +090043 return 7;
Namhyung Kimea251d52012-09-03 11:53:06 +090044}
45
46static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
47{
48 double percent = 100.0 * he->period_sys / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +090049 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
Namhyung Kimea251d52012-09-03 11:53:06 +090050}
51
52static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
53{
54 double percent = 100.0 * he->period_sys / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +090055 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
Namhyung Kim9ffad982012-09-03 11:53:07 +090056
57 return scnprintf(hpp->buf, hpp->size, fmt, percent);
Namhyung Kimea251d52012-09-03 11:53:06 +090058}
59
60static int hpp__header_overhead_us(struct perf_hpp *hpp)
61{
Namhyung Kim721b3112012-09-12 15:35:05 +090062 const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
Namhyung Kim9ffad982012-09-03 11:53:07 +090063
64 return scnprintf(hpp->buf, hpp->size, fmt, "user");
Namhyung Kimea251d52012-09-03 11:53:06 +090065}
66
Irina Tirdea1d037ca2012-09-11 01:15:03 +030067static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +090068{
Namhyung Kim721b3112012-09-12 15:35:05 +090069 return 7;
Namhyung Kimea251d52012-09-03 11:53:06 +090070}
71
72static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
73{
74 double percent = 100.0 * he->period_us / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +090075 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
Namhyung Kimea251d52012-09-03 11:53:06 +090076}
77
78static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
79{
80 double percent = 100.0 * he->period_us / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +090081 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
Namhyung Kim9ffad982012-09-03 11:53:07 +090082
83 return scnprintf(hpp->buf, hpp->size, fmt, percent);
Namhyung Kimea251d52012-09-03 11:53:06 +090084}
85
86static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
87{
88 return scnprintf(hpp->buf, hpp->size, "guest sys");
89}
90
Irina Tirdea1d037ca2012-09-11 01:15:03 +030091static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +090092{
93 return 9;
94}
95
96static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
97 struct hist_entry *he)
98{
99 double percent = 100.0 * he->period_guest_sys / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +0900100 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
Namhyung Kimea251d52012-09-03 11:53:06 +0900101}
102
103static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
104 struct hist_entry *he)
105{
106 double percent = 100.0 * he->period_guest_sys / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +0900107 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
Namhyung Kim9ffad982012-09-03 11:53:07 +0900108
109 return scnprintf(hpp->buf, hpp->size, fmt, percent);
Namhyung Kimea251d52012-09-03 11:53:06 +0900110}
111
112static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
113{
114 return scnprintf(hpp->buf, hpp->size, "guest usr");
115}
116
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300117static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +0900118{
119 return 9;
120}
121
122static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
123 struct hist_entry *he)
124{
125 double percent = 100.0 * he->period_guest_us / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +0900126 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
Namhyung Kimea251d52012-09-03 11:53:06 +0900127}
128
129static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
130 struct hist_entry *he)
131{
132 double percent = 100.0 * he->period_guest_us / hpp->total_period;
Namhyung Kim721b3112012-09-12 15:35:05 +0900133 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
Namhyung Kim9ffad982012-09-03 11:53:07 +0900134
135 return scnprintf(hpp->buf, hpp->size, fmt, percent);
Namhyung Kimea251d52012-09-03 11:53:06 +0900136}
137
Jiri Olsa5395a042012-10-04 21:49:37 +0900138static int hpp__header_baseline(struct perf_hpp *hpp)
139{
140 return scnprintf(hpp->buf, hpp->size, "Baseline");
141}
142
143static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
144{
145 return 8;
146}
147
148static double baseline_percent(struct hist_entry *he)
149{
150 struct hist_entry *pair = he->pair;
151 struct hists *pair_hists = pair ? pair->hists : NULL;
152 double percent = 0.0;
153
154 if (pair) {
155 u64 total_period = pair_hists->stats.total_period;
156 u64 base_period = pair->period;
157
158 percent = 100.0 * base_period / total_period;
159 }
160
161 return percent;
162}
163
164static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
165{
166 double percent = baseline_percent(he);
167
168 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
169}
170
171static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
172{
173 double percent = baseline_percent(he);
174 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
175
176 return scnprintf(hpp->buf, hpp->size, fmt, percent);
177}
178
Namhyung Kimea251d52012-09-03 11:53:06 +0900179static int hpp__header_samples(struct perf_hpp *hpp)
180{
Namhyung Kim9ffad982012-09-03 11:53:07 +0900181 const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
182
183 return scnprintf(hpp->buf, hpp->size, fmt, "Samples");
Namhyung Kimea251d52012-09-03 11:53:06 +0900184}
185
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300186static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +0900187{
188 return 11;
189}
190
191static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
192{
Namhyung Kim9ffad982012-09-03 11:53:07 +0900193 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
194
195 return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events);
Namhyung Kimea251d52012-09-03 11:53:06 +0900196}
197
198static int hpp__header_period(struct perf_hpp *hpp)
199{
Namhyung Kim9ffad982012-09-03 11:53:07 +0900200 const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
201
202 return scnprintf(hpp->buf, hpp->size, fmt, "Period");
Namhyung Kimea251d52012-09-03 11:53:06 +0900203}
204
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300205static int hpp__width_period(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +0900206{
207 return 12;
208}
209
210static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
211{
Namhyung Kim9ffad982012-09-03 11:53:07 +0900212 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
213
214 return scnprintf(hpp->buf, hpp->size, fmt, he->period);
Namhyung Kimea251d52012-09-03 11:53:06 +0900215}
216
217static int hpp__header_delta(struct perf_hpp *hpp)
218{
Namhyung Kim9ffad982012-09-03 11:53:07 +0900219 const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
220
221 return scnprintf(hpp->buf, hpp->size, fmt, "Delta");
Namhyung Kimea251d52012-09-03 11:53:06 +0900222}
223
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300224static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +0900225{
226 return 7;
227}
228
229static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
230{
Jiri Olsa41724e42012-10-04 21:49:38 +0900231 struct hist_entry *pair = he->pair;
232 struct hists *pair_hists = pair ? pair->hists : NULL;
Namhyung Kimea251d52012-09-03 11:53:06 +0900233 u64 old_total, new_total;
234 double old_percent = 0, new_percent = 0;
235 double diff;
Namhyung Kim9ffad982012-09-03 11:53:07 +0900236 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
237 char buf[32] = " ";
Namhyung Kimea251d52012-09-03 11:53:06 +0900238
Jiri Olsa41724e42012-10-04 21:49:38 +0900239 old_total = pair_hists ? pair_hists->stats.total_period : 0;
240 if (old_total > 0 && pair)
241 old_percent = 100.0 * pair->period / old_total;
Namhyung Kimea251d52012-09-03 11:53:06 +0900242
243 new_total = hpp->total_period;
244 if (new_total > 0)
245 new_percent = 100.0 * he->period / new_total;
246
247 diff = new_percent - old_percent;
Namhyung Kim9ffad982012-09-03 11:53:07 +0900248 if (fabs(diff) >= 0.01)
249 scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
Namhyung Kimea251d52012-09-03 11:53:06 +0900250
Namhyung Kim9ffad982012-09-03 11:53:07 +0900251 return scnprintf(hpp->buf, hpp->size, fmt, buf);
Namhyung Kimea251d52012-09-03 11:53:06 +0900252}
253
254static int hpp__header_displ(struct perf_hpp *hpp)
255{
256 return scnprintf(hpp->buf, hpp->size, "Displ.");
257}
258
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300259static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
Namhyung Kimea251d52012-09-03 11:53:06 +0900260{
261 return 6;
262}
263
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300264static int hpp__entry_displ(struct perf_hpp *hpp,
Jiri Olsadd464342012-10-04 21:49:36 +0900265 struct hist_entry *he)
Namhyung Kimea251d52012-09-03 11:53:06 +0900266{
Jiri Olsadd464342012-10-04 21:49:36 +0900267 struct hist_entry *pair = he->pair;
268 long displacement = pair ? pair->position - he->position : 0;
Namhyung Kim9ffad982012-09-03 11:53:07 +0900269 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
270 char buf[32] = " ";
Namhyung Kimea251d52012-09-03 11:53:06 +0900271
Jiri Olsadd464342012-10-04 21:49:36 +0900272 if (displacement)
273 scnprintf(buf, sizeof(buf), "%+4ld", displacement);
Namhyung Kimea251d52012-09-03 11:53:06 +0900274
Namhyung Kim9ffad982012-09-03 11:53:07 +0900275 return scnprintf(hpp->buf, hpp->size, fmt, buf);
Namhyung Kimea251d52012-09-03 11:53:06 +0900276}
277
278#define HPP__COLOR_PRINT_FNS(_name) \
279 .header = hpp__header_ ## _name, \
280 .width = hpp__width_ ## _name, \
281 .color = hpp__color_ ## _name, \
282 .entry = hpp__entry_ ## _name
283
284#define HPP__PRINT_FNS(_name) \
285 .header = hpp__header_ ## _name, \
286 .width = hpp__width_ ## _name, \
287 .entry = hpp__entry_ ## _name
288
289struct perf_hpp_fmt perf_hpp__format[] = {
Jiri Olsa5395a042012-10-04 21:49:37 +0900290 { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
Namhyung Kimea251d52012-09-03 11:53:06 +0900291 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
292 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
293 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
294 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) },
295 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
296 { .cond = false, HPP__PRINT_FNS(samples) },
297 { .cond = false, HPP__PRINT_FNS(period) },
298 { .cond = false, HPP__PRINT_FNS(delta) },
299 { .cond = false, HPP__PRINT_FNS(displ) }
300};
301
302#undef HPP__COLOR_PRINT_FNS
303#undef HPP__PRINT_FNS
304
Jiri Olsa1d778222012-10-04 21:49:39 +0900305void perf_hpp__init(void)
Namhyung Kimea251d52012-09-03 11:53:06 +0900306{
307 if (symbol_conf.show_cpu_utilization) {
308 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
309 perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true;
310
311 if (perf_guest) {
312 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true;
313 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true;
314 }
315 }
316
317 if (symbol_conf.show_nr_samples)
318 perf_hpp__format[PERF_HPP__SAMPLES].cond = true;
319
320 if (symbol_conf.show_total_period)
321 perf_hpp__format[PERF_HPP__PERIOD].cond = true;
Jiri Olsa1d778222012-10-04 21:49:39 +0900322}
Namhyung Kimea251d52012-09-03 11:53:06 +0900323
Jiri Olsa1d778222012-10-04 21:49:39 +0900324void perf_hpp__column_enable(unsigned col, bool enable)
325{
326 BUG_ON(col >= PERF_HPP__MAX_INDEX);
327 perf_hpp__format[col].cond = enable;
Namhyung Kimea251d52012-09-03 11:53:06 +0900328}
329
330static inline void advance_hpp(struct perf_hpp *hpp, int inc)
331{
332 hpp->buf += inc;
333 hpp->size -= inc;
334}
335
336int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
337 bool color)
338{
339 const char *sep = symbol_conf.field_sep;
340 char *start = hpp->buf;
341 int i, ret;
Jiri Olsa5395a042012-10-04 21:49:37 +0900342 bool first = true;
Namhyung Kimea251d52012-09-03 11:53:06 +0900343
344 if (symbol_conf.exclude_other && !he->parent)
345 return 0;
346
347 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
348 if (!perf_hpp__format[i].cond)
349 continue;
350
Jiri Olsa5395a042012-10-04 21:49:37 +0900351 if (!sep || !first) {
Namhyung Kimea251d52012-09-03 11:53:06 +0900352 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
353 advance_hpp(hpp, ret);
Jiri Olsa5395a042012-10-04 21:49:37 +0900354 first = false;
Namhyung Kimea251d52012-09-03 11:53:06 +0900355 }
356
357 if (color && perf_hpp__format[i].color)
358 ret = perf_hpp__format[i].color(hpp, he);
359 else
360 ret = perf_hpp__format[i].entry(hpp, he);
361
362 advance_hpp(hpp, ret);
363 }
364
365 return hpp->buf - start;
366}
367
368int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
369 struct hists *hists)
370{
371 const char *sep = symbol_conf.field_sep;
372 struct sort_entry *se;
373 int ret = 0;
374
375 list_for_each_entry(se, &hist_entry__sort_list, list) {
376 if (se->elide)
377 continue;
378
379 ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
380 ret += se->se_snprintf(he, s + ret, size - ret,
381 hists__col_len(hists, se->se_width_idx));
382 }
383
384 return ret;
385}
Namhyung Kim7e62ef42012-09-03 11:53:08 +0900386
387/*
388 * See hists__fprintf to match the column widths
389 */
390unsigned int hists__sort_list_width(struct hists *hists)
391{
392 struct sort_entry *se;
393 int i, ret = 0;
394
395 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
396 if (!perf_hpp__format[i].cond)
397 continue;
398 if (i)
399 ret += 2;
400
401 ret += perf_hpp__format[i].width(NULL);
402 }
403
404 list_for_each_entry(se, &hist_entry__sort_list, list)
405 if (!se->elide)
406 ret += 2 + hists__col_len(hists, se->se_width_idx);
407
408 if (verbose) /* Addr + origin */
409 ret += 3 + BITS_PER_LONG / 4;
410
411 return ret;
412}