diff options
Diffstat (limited to 'tools/perf/ui/hist.c')
-rw-r--r-- | tools/perf/ui/hist.c | 145 |
1 files changed, 91 insertions, 54 deletions
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index e3f8cd46e7d7..f5a1e4f65263 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -8,9 +8,7 @@ | |||
8 | /* hist period print (hpp) functions */ | 8 | /* hist period print (hpp) functions */ |
9 | static int hpp__header_overhead(struct perf_hpp *hpp) | 9 | static int hpp__header_overhead(struct perf_hpp *hpp) |
10 | { | 10 | { |
11 | const char *fmt = hpp->ptr ? "Baseline" : "Overhead"; | 11 | return scnprintf(hpp->buf, hpp->size, "Overhead"); |
12 | |||
13 | return scnprintf(hpp->buf, hpp->size, fmt); | ||
14 | } | 12 | } |
15 | 13 | ||
16 | static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) | 14 | static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) |
@@ -20,38 +18,18 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) | |||
20 | 18 | ||
21 | static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) | 19 | static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) |
22 | { | 20 | { |
23 | double percent = 100.0 * he->period / hpp->total_period; | 21 | struct hists *hists = he->hists; |
24 | 22 | double percent = 100.0 * he->stat.period / hists->stats.total_period; | |
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 | 23 | ||
36 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); | 24 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); |
37 | } | 25 | } |
38 | 26 | ||
39 | static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) | 27 | static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) |
40 | { | 28 | { |
41 | double percent = 100.0 * he->period / hpp->total_period; | 29 | struct hists *hists = he->hists; |
30 | double percent = 100.0 * he->stat.period / hists->stats.total_period; | ||
42 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; | 31 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; |
43 | 32 | ||
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, fmt, percent); | 33 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
56 | } | 34 | } |
57 | 35 | ||
@@ -69,13 +47,16 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) | |||
69 | 47 | ||
70 | static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) | 48 | static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) |
71 | { | 49 | { |
72 | double percent = 100.0 * he->period_sys / hpp->total_period; | 50 | struct hists *hists = he->hists; |
51 | double percent = 100.0 * he->stat.period_sys / hists->stats.total_period; | ||
52 | |||
73 | return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); | 53 | return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); |
74 | } | 54 | } |
75 | 55 | ||
76 | static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) | 56 | static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) |
77 | { | 57 | { |
78 | double percent = 100.0 * he->period_sys / hpp->total_period; | 58 | struct hists *hists = he->hists; |
59 | double percent = 100.0 * he->stat.period_sys / hists->stats.total_period; | ||
79 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; | 60 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; |
80 | 61 | ||
81 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 62 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
@@ -95,13 +76,16 @@ static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused) | |||
95 | 76 | ||
96 | static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) | 77 | static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) |
97 | { | 78 | { |
98 | double percent = 100.0 * he->period_us / hpp->total_period; | 79 | struct hists *hists = he->hists; |
80 | double percent = 100.0 * he->stat.period_us / hists->stats.total_period; | ||
81 | |||
99 | return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); | 82 | return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); |
100 | } | 83 | } |
101 | 84 | ||
102 | static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) | 85 | static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) |
103 | { | 86 | { |
104 | double percent = 100.0 * he->period_us / hpp->total_period; | 87 | struct hists *hists = he->hists; |
88 | double percent = 100.0 * he->stat.period_us / hists->stats.total_period; | ||
105 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; | 89 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; |
106 | 90 | ||
107 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 91 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
@@ -120,14 +104,17 @@ static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused) | |||
120 | static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, | 104 | static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, |
121 | struct hist_entry *he) | 105 | struct hist_entry *he) |
122 | { | 106 | { |
123 | double percent = 100.0 * he->period_guest_sys / hpp->total_period; | 107 | struct hists *hists = he->hists; |
108 | double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period; | ||
109 | |||
124 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); | 110 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); |
125 | } | 111 | } |
126 | 112 | ||
127 | static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, | 113 | static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, |
128 | struct hist_entry *he) | 114 | struct hist_entry *he) |
129 | { | 115 | { |
130 | double percent = 100.0 * he->period_guest_sys / hpp->total_period; | 116 | struct hists *hists = he->hists; |
117 | double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period; | ||
131 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; | 118 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; |
132 | 119 | ||
133 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 120 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
@@ -146,19 +133,63 @@ static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused) | |||
146 | static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, | 133 | static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, |
147 | struct hist_entry *he) | 134 | struct hist_entry *he) |
148 | { | 135 | { |
149 | double percent = 100.0 * he->period_guest_us / hpp->total_period; | 136 | struct hists *hists = he->hists; |
137 | double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period; | ||
138 | |||
150 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); | 139 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); |
151 | } | 140 | } |
152 | 141 | ||
153 | static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, | 142 | static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, |
154 | struct hist_entry *he) | 143 | struct hist_entry *he) |
155 | { | 144 | { |
156 | double percent = 100.0 * he->period_guest_us / hpp->total_period; | 145 | struct hists *hists = he->hists; |
146 | double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period; | ||
157 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; | 147 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; |
158 | 148 | ||
159 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 149 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
160 | } | 150 | } |
161 | 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 | |||
162 | static int hpp__header_samples(struct perf_hpp *hpp) | 193 | static int hpp__header_samples(struct perf_hpp *hpp) |
163 | { | 194 | { |
164 | const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; | 195 | const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; |
@@ -175,7 +206,7 @@ static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he) | |||
175 | { | 206 | { |
176 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; | 207 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; |
177 | 208 | ||
178 | return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events); | 209 | return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events); |
179 | } | 210 | } |
180 | 211 | ||
181 | static int hpp__header_period(struct perf_hpp *hpp) | 212 | static int hpp__header_period(struct perf_hpp *hpp) |
@@ -194,7 +225,7 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he) | |||
194 | { | 225 | { |
195 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; | 226 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; |
196 | 227 | ||
197 | return scnprintf(hpp->buf, hpp->size, fmt, he->period); | 228 | return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period); |
198 | } | 229 | } |
199 | 230 | ||
200 | static int hpp__header_delta(struct perf_hpp *hpp) | 231 | static int hpp__header_delta(struct perf_hpp *hpp) |
@@ -211,20 +242,22 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused) | |||
211 | 242 | ||
212 | static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) | 243 | static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) |
213 | { | 244 | { |
214 | struct hists *pair_hists = hpp->ptr; | 245 | struct hist_entry *pair = he->pair; |
246 | struct hists *pair_hists = pair ? pair->hists : NULL; | ||
247 | struct hists *hists = he->hists; | ||
215 | u64 old_total, new_total; | 248 | u64 old_total, new_total; |
216 | double old_percent = 0, new_percent = 0; | 249 | double old_percent = 0, new_percent = 0; |
217 | double diff; | 250 | double diff; |
218 | const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; | 251 | const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; |
219 | char buf[32] = " "; | 252 | char buf[32] = " "; |
220 | 253 | ||
221 | old_total = pair_hists->stats.total_period; | 254 | old_total = pair_hists ? pair_hists->stats.total_period : 0; |
222 | if (old_total > 0 && he->pair) | 255 | if (old_total > 0 && pair) |
223 | old_percent = 100.0 * he->pair->period / old_total; | 256 | old_percent = 100.0 * pair->stat.period / old_total; |
224 | 257 | ||
225 | new_total = hpp->total_period; | 258 | new_total = hists->stats.total_period; |
226 | if (new_total > 0) | 259 | if (new_total > 0) |
227 | new_percent = 100.0 * he->period / new_total; | 260 | new_percent = 100.0 * he->stat.period / new_total; |
228 | 261 | ||
229 | diff = new_percent - old_percent; | 262 | diff = new_percent - old_percent; |
230 | if (fabs(diff) >= 0.01) | 263 | if (fabs(diff) >= 0.01) |
@@ -244,13 +277,15 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused) | |||
244 | } | 277 | } |
245 | 278 | ||
246 | static int hpp__entry_displ(struct perf_hpp *hpp, | 279 | static int hpp__entry_displ(struct perf_hpp *hpp, |
247 | struct hist_entry *he __maybe_unused) | 280 | struct hist_entry *he) |
248 | { | 281 | { |
282 | struct hist_entry *pair = he->pair; | ||
283 | long displacement = pair ? pair->position - he->position : 0; | ||
249 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; | 284 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; |
250 | char buf[32] = " "; | 285 | char buf[32] = " "; |
251 | 286 | ||
252 | if (hpp->displacement) | 287 | if (displacement) |
253 | scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement); | 288 | scnprintf(buf, sizeof(buf), "%+4ld", displacement); |
254 | 289 | ||
255 | return scnprintf(hpp->buf, hpp->size, fmt, buf); | 290 | return scnprintf(hpp->buf, hpp->size, fmt, buf); |
256 | } | 291 | } |
@@ -267,6 +302,7 @@ static int hpp__entry_displ(struct perf_hpp *hpp, | |||
267 | .entry = hpp__entry_ ## _name | 302 | .entry = hpp__entry_ ## _name |
268 | 303 | ||
269 | struct perf_hpp_fmt perf_hpp__format[] = { | 304 | struct perf_hpp_fmt perf_hpp__format[] = { |
305 | { .cond = false, HPP__COLOR_PRINT_FNS(baseline) }, | ||
270 | { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, | 306 | { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, |
271 | { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, | 307 | { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, |
272 | { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, | 308 | { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, |
@@ -281,7 +317,7 @@ struct perf_hpp_fmt perf_hpp__format[] = { | |||
281 | #undef HPP__COLOR_PRINT_FNS | 317 | #undef HPP__COLOR_PRINT_FNS |
282 | #undef HPP__PRINT_FNS | 318 | #undef HPP__PRINT_FNS |
283 | 319 | ||
284 | void perf_hpp__init(bool need_pair, bool show_displacement) | 320 | void perf_hpp__init(void) |
285 | { | 321 | { |
286 | if (symbol_conf.show_cpu_utilization) { | 322 | if (symbol_conf.show_cpu_utilization) { |
287 | perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; | 323 | perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; |
@@ -298,13 +334,12 @@ void perf_hpp__init(bool need_pair, bool show_displacement) | |||
298 | 334 | ||
299 | if (symbol_conf.show_total_period) | 335 | if (symbol_conf.show_total_period) |
300 | perf_hpp__format[PERF_HPP__PERIOD].cond = true; | 336 | perf_hpp__format[PERF_HPP__PERIOD].cond = true; |
337 | } | ||
301 | 338 | ||
302 | if (need_pair) { | 339 | void perf_hpp__column_enable(unsigned col, bool enable) |
303 | perf_hpp__format[PERF_HPP__DELTA].cond = true; | 340 | { |
304 | 341 | BUG_ON(col >= PERF_HPP__MAX_INDEX); | |
305 | if (show_displacement) | 342 | perf_hpp__format[col].cond = enable; |
306 | perf_hpp__format[PERF_HPP__DISPL].cond = true; | ||
307 | } | ||
308 | } | 343 | } |
309 | 344 | ||
310 | static inline void advance_hpp(struct perf_hpp *hpp, int inc) | 345 | static inline void advance_hpp(struct perf_hpp *hpp, int inc) |
@@ -319,6 +354,7 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, | |||
319 | const char *sep = symbol_conf.field_sep; | 354 | const char *sep = symbol_conf.field_sep; |
320 | char *start = hpp->buf; | 355 | char *start = hpp->buf; |
321 | int i, ret; | 356 | int i, ret; |
357 | bool first = true; | ||
322 | 358 | ||
323 | if (symbol_conf.exclude_other && !he->parent) | 359 | if (symbol_conf.exclude_other && !he->parent) |
324 | return 0; | 360 | return 0; |
@@ -327,9 +363,10 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, | |||
327 | if (!perf_hpp__format[i].cond) | 363 | if (!perf_hpp__format[i].cond) |
328 | continue; | 364 | continue; |
329 | 365 | ||
330 | if (!sep || i > 0) { | 366 | if (!sep || !first) { |
331 | ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); | 367 | ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); |
332 | advance_hpp(hpp, ret); | 368 | advance_hpp(hpp, ret); |
369 | first = false; | ||
333 | } | 370 | } |
334 | 371 | ||
335 | if (color && perf_hpp__format[i].color) | 372 | if (color && perf_hpp__format[i].color) |