]> Pileus Git - ~andy/linux/blob - tools/perf/ui/hist.c
Merge tag 'omap-for-v3.8/cleanup-timer-signed' of git://git.kernel.org/pub/scm/linux...
[~andy/linux] / tools / perf / ui / hist.c
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 */
9 static int hpp__header_overhead(struct perf_hpp *hpp)
10 {
11         return scnprintf(hpp->buf, hpp->size, "Overhead");
12 }
13
14 static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
15 {
16         return 8;
17 }
18
19 static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
20 {
21         struct hists *hists = he->hists;
22         double percent = 100.0 * he->stat.period / hists->stats.total_period;
23
24         return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
25 }
26
27 static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
28 {
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%%";
32
33         return scnprintf(hpp->buf, hpp->size, fmt, percent);
34 }
35
36 static int hpp__header_overhead_sys(struct perf_hpp *hpp)
37 {
38         const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
39
40         return scnprintf(hpp->buf, hpp->size, fmt, "sys");
41 }
42
43 static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
44 {
45         return 7;
46 }
47
48 static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
49 {
50         struct hists *hists = he->hists;
51         double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
52
53         return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
54 }
55
56 static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
57 {
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%%";
61
62         return scnprintf(hpp->buf, hpp->size, fmt, percent);
63 }
64
65 static int hpp__header_overhead_us(struct perf_hpp *hpp)
66 {
67         const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
68
69         return scnprintf(hpp->buf, hpp->size, fmt, "user");
70 }
71
72 static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
73 {
74         return 7;
75 }
76
77 static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
78 {
79         struct hists *hists = he->hists;
80         double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
81
82         return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
83 }
84
85 static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
86 {
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%%";
90
91         return scnprintf(hpp->buf, hpp->size, fmt, percent);
92 }
93
94 static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
95 {
96         return scnprintf(hpp->buf, hpp->size, "guest sys");
97 }
98
99 static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
100 {
101         return 9;
102 }
103
104 static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
105                                          struct hist_entry *he)
106 {
107         struct hists *hists = he->hists;
108         double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
109
110         return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
111 }
112
113 static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
114                                          struct hist_entry *he)
115 {
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%% ";
119
120         return scnprintf(hpp->buf, hpp->size, fmt, percent);
121 }
122
123 static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
124 {
125         return scnprintf(hpp->buf, hpp->size, "guest usr");
126 }
127
128 static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
129 {
130         return 9;
131 }
132
133 static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
134                                         struct hist_entry *he)
135 {
136         struct hists *hists = he->hists;
137         double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
138
139         return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
140 }
141
142 static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
143                                         struct hist_entry *he)
144 {
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%% ";
148
149         return scnprintf(hpp->buf, hpp->size, fmt, percent);
150 }
151
152 static int hpp__header_baseline(struct perf_hpp *hpp)
153 {
154         return scnprintf(hpp->buf, hpp->size, "Baseline");
155 }
156
157 static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
158 {
159         return 8;
160 }
161
162 static double baseline_percent(struct hist_entry *he)
163 {
164         struct hist_entry *pair = he->pair;
165         struct hists *pair_hists = pair ? pair->hists : NULL;
166         double percent = 0.0;
167
168         if (pair) {
169                 u64 total_period = pair_hists->stats.total_period;
170                 u64 base_period  = pair->stat.period;
171
172                 percent = 100.0 * base_period / total_period;
173         }
174
175         return percent;
176 }
177
178 static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
179 {
180         double percent = baseline_percent(he);
181
182         return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
183 }
184
185 static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
186 {
187         double percent = baseline_percent(he);
188         const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
189
190         return scnprintf(hpp->buf, hpp->size, fmt, percent);
191 }
192
193 static int hpp__header_samples(struct perf_hpp *hpp)
194 {
195         const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
196
197         return scnprintf(hpp->buf, hpp->size, fmt, "Samples");
198 }
199
200 static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused)
201 {
202         return 11;
203 }
204
205 static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
206 {
207         const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
208
209         return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
210 }
211
212 static int hpp__header_period(struct perf_hpp *hpp)
213 {
214         const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
215
216         return scnprintf(hpp->buf, hpp->size, fmt, "Period");
217 }
218
219 static int hpp__width_period(struct perf_hpp *hpp __maybe_unused)
220 {
221         return 12;
222 }
223
224 static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
225 {
226         const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
227
228         return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
229 }
230
231 static int hpp__header_delta(struct perf_hpp *hpp)
232 {
233         const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
234
235         return scnprintf(hpp->buf, hpp->size, fmt, "Delta");
236 }
237
238 static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
239 {
240         return 7;
241 }
242
243 static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
244 {
245         struct hist_entry *pair = he->pair;
246         struct hists *pair_hists = pair ? pair->hists : NULL;
247         struct hists *hists = he->hists;
248         u64 old_total, new_total;
249         double old_percent = 0, new_percent = 0;
250         double diff;
251         const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
252         char buf[32] = " ";
253
254         old_total = pair_hists ? pair_hists->stats.total_period : 0;
255         if (old_total > 0 && pair)
256                 old_percent = 100.0 * pair->stat.period / old_total;
257
258         new_total = hists->stats.total_period;
259         if (new_total > 0)
260                 new_percent = 100.0 * he->stat.period / new_total;
261
262         diff = new_percent - old_percent;
263         if (fabs(diff) >= 0.01)
264                 scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
265
266         return scnprintf(hpp->buf, hpp->size, fmt, buf);
267 }
268
269 static int hpp__header_displ(struct perf_hpp *hpp)
270 {
271         return scnprintf(hpp->buf, hpp->size, "Displ.");
272 }
273
274 static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
275 {
276         return 6;
277 }
278
279 static int hpp__entry_displ(struct perf_hpp *hpp,
280                             struct hist_entry *he)
281 {
282         struct hist_entry *pair = he->pair;
283         long displacement = pair ? pair->position - he->position : 0;
284         const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
285         char buf[32] = " ";
286
287         if (displacement)
288                 scnprintf(buf, sizeof(buf), "%+4ld", displacement);
289
290         return scnprintf(hpp->buf, hpp->size, fmt, buf);
291 }
292
293 #define HPP__COLOR_PRINT_FNS(_name)             \
294         .header = hpp__header_ ## _name,                \
295         .width  = hpp__width_ ## _name,         \
296         .color  = hpp__color_ ## _name,         \
297         .entry  = hpp__entry_ ## _name
298
299 #define HPP__PRINT_FNS(_name)                   \
300         .header = hpp__header_ ## _name,                \
301         .width  = hpp__width_ ## _name,         \
302         .entry  = hpp__entry_ ## _name
303
304 struct perf_hpp_fmt perf_hpp__format[] = {
305         { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
306         { .cond = true,  HPP__COLOR_PRINT_FNS(overhead) },
307         { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
308         { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
309         { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) },
310         { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
311         { .cond = false, HPP__PRINT_FNS(samples) },
312         { .cond = false, HPP__PRINT_FNS(period) },
313         { .cond = false, HPP__PRINT_FNS(delta) },
314         { .cond = false, HPP__PRINT_FNS(displ) }
315 };
316
317 #undef HPP__COLOR_PRINT_FNS
318 #undef HPP__PRINT_FNS
319
320 void perf_hpp__init(void)
321 {
322         if (symbol_conf.show_cpu_utilization) {
323                 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
324                 perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true;
325
326                 if (perf_guest) {
327                         perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true;
328                         perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true;
329                 }
330         }
331
332         if (symbol_conf.show_nr_samples)
333                 perf_hpp__format[PERF_HPP__SAMPLES].cond = true;
334
335         if (symbol_conf.show_total_period)
336                 perf_hpp__format[PERF_HPP__PERIOD].cond = true;
337 }
338
339 void perf_hpp__column_enable(unsigned col, bool enable)
340 {
341         BUG_ON(col >= PERF_HPP__MAX_INDEX);
342         perf_hpp__format[col].cond = enable;
343 }
344
345 static inline void advance_hpp(struct perf_hpp *hpp, int inc)
346 {
347         hpp->buf  += inc;
348         hpp->size -= inc;
349 }
350
351 int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
352                                 bool color)
353 {
354         const char *sep = symbol_conf.field_sep;
355         char *start = hpp->buf;
356         int i, ret;
357         bool first = true;
358
359         if (symbol_conf.exclude_other && !he->parent)
360                 return 0;
361
362         for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
363                 if (!perf_hpp__format[i].cond)
364                         continue;
365
366                 if (!sep || !first) {
367                         ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
368                         advance_hpp(hpp, ret);
369                         first = false;
370                 }
371
372                 if (color && perf_hpp__format[i].color)
373                         ret = perf_hpp__format[i].color(hpp, he);
374                 else
375                         ret = perf_hpp__format[i].entry(hpp, he);
376
377                 advance_hpp(hpp, ret);
378         }
379
380         return hpp->buf - start;
381 }
382
383 int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
384                               struct hists *hists)
385 {
386         const char *sep = symbol_conf.field_sep;
387         struct sort_entry *se;
388         int ret = 0;
389
390         list_for_each_entry(se, &hist_entry__sort_list, list) {
391                 if (se->elide)
392                         continue;
393
394                 ret += scnprintf(s + ret, size - ret, "%s", sep ?: "  ");
395                 ret += se->se_snprintf(he, s + ret, size - ret,
396                                        hists__col_len(hists, se->se_width_idx));
397         }
398
399         return ret;
400 }
401
402 /*
403  * See hists__fprintf to match the column widths
404  */
405 unsigned int hists__sort_list_width(struct hists *hists)
406 {
407         struct sort_entry *se;
408         int i, ret = 0;
409
410         for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
411                 if (!perf_hpp__format[i].cond)
412                         continue;
413                 if (i)
414                         ret += 2;
415
416                 ret += perf_hpp__format[i].width(NULL);
417         }
418
419         list_for_each_entry(se, &hist_entry__sort_list, list)
420                 if (!se->elide)
421                         ret += 2 + hists__col_len(hists, se->se_width_idx);
422
423         if (verbose) /* Addr + origin */
424                 ret += 3 + BITS_PER_LONG / 4;
425
426         return ret;
427 }