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) |
