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