at v3.8-rc2 527 lines 14 kB view raw
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 */ 9static int hpp__header_overhead(struct perf_hpp *hpp) 10{ 11 return scnprintf(hpp->buf, hpp->size, "Overhead"); 12} 13 14static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) 15{ 16 return 8; 17} 18 19static 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 27static 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 36static 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 43static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) 44{ 45 return 7; 46} 47 48static 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 56static 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 65static 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 72static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused) 73{ 74 return 7; 75} 76 77static 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 85static 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 94static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp) 95{ 96 return scnprintf(hpp->buf, hpp->size, "guest sys"); 97} 98 99static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused) 100{ 101 return 9; 102} 103 104static 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 113static 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 123static int hpp__header_overhead_guest_us(struct perf_hpp *hpp) 124{ 125 return scnprintf(hpp->buf, hpp->size, "guest usr"); 126} 127 128static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused) 129{ 130 return 9; 131} 132 133static 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 142static 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 152static int hpp__header_baseline(struct perf_hpp *hpp) 153{ 154 return scnprintf(hpp->buf, hpp->size, "Baseline"); 155} 156 157static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused) 158{ 159 return 8; 160} 161 162static double baseline_percent(struct hist_entry *he) 163{ 164 struct hist_entry *pair = hist_entry__next_pair(he); 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 178static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he) 179{ 180 double percent = baseline_percent(he); 181 182 if (hist_entry__has_pairs(he)) 183 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); 184 else 185 return scnprintf(hpp->buf, hpp->size, " "); 186} 187 188static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he) 189{ 190 double percent = baseline_percent(he); 191 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; 192 193 if (hist_entry__has_pairs(he) || symbol_conf.field_sep) 194 return scnprintf(hpp->buf, hpp->size, fmt, percent); 195 else 196 return scnprintf(hpp->buf, hpp->size, " "); 197} 198 199static int hpp__header_samples(struct perf_hpp *hpp) 200{ 201 const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; 202 203 return scnprintf(hpp->buf, hpp->size, fmt, "Samples"); 204} 205 206static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused) 207{ 208 return 11; 209} 210 211static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he) 212{ 213 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; 214 215 return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events); 216} 217 218static int hpp__header_period(struct perf_hpp *hpp) 219{ 220 const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; 221 222 return scnprintf(hpp->buf, hpp->size, fmt, "Period"); 223} 224 225static int hpp__width_period(struct perf_hpp *hpp __maybe_unused) 226{ 227 return 12; 228} 229 230static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he) 231{ 232 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; 233 234 return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period); 235} 236 237static int hpp__header_period_baseline(struct perf_hpp *hpp) 238{ 239 const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; 240 241 return scnprintf(hpp->buf, hpp->size, fmt, "Period Base"); 242} 243 244static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused) 245{ 246 return 12; 247} 248 249static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he) 250{ 251 struct hist_entry *pair = hist_entry__next_pair(he); 252 u64 period = pair ? pair->stat.period : 0; 253 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; 254 255 return scnprintf(hpp->buf, hpp->size, fmt, period); 256} 257static int hpp__header_delta(struct perf_hpp *hpp) 258{ 259 const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; 260 261 return scnprintf(hpp->buf, hpp->size, fmt, "Delta"); 262} 263 264static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused) 265{ 266 return 7; 267} 268 269static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) 270{ 271 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; 272 char buf[32] = " "; 273 double diff; 274 275 if (he->diff.computed) 276 diff = he->diff.period_ratio_delta; 277 else 278 diff = perf_diff__compute_delta(he); 279 280 if (fabs(diff) >= 0.01) 281 scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); 282 283 return scnprintf(hpp->buf, hpp->size, fmt, buf); 284} 285 286static int hpp__header_ratio(struct perf_hpp *hpp) 287{ 288 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; 289 290 return scnprintf(hpp->buf, hpp->size, fmt, "Ratio"); 291} 292 293static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused) 294{ 295 return 14; 296} 297 298static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he) 299{ 300 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; 301 char buf[32] = " "; 302 double ratio; 303 304 if (he->diff.computed) 305 ratio = he->diff.period_ratio; 306 else 307 ratio = perf_diff__compute_ratio(he); 308 309 if (ratio > 0.0) 310 scnprintf(buf, sizeof(buf), "%+14.6F", ratio); 311 312 return scnprintf(hpp->buf, hpp->size, fmt, buf); 313} 314 315static int hpp__header_wdiff(struct perf_hpp *hpp) 316{ 317 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; 318 319 return scnprintf(hpp->buf, hpp->size, fmt, "Weighted diff"); 320} 321 322static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused) 323{ 324 return 14; 325} 326 327static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he) 328{ 329 const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; 330 char buf[32] = " "; 331 s64 wdiff; 332 333 if (he->diff.computed) 334 wdiff = he->diff.wdiff; 335 else 336 wdiff = perf_diff__compute_wdiff(he); 337 338 if (wdiff != 0) 339 scnprintf(buf, sizeof(buf), "%14ld", wdiff); 340 341 return scnprintf(hpp->buf, hpp->size, fmt, buf); 342} 343 344static int hpp__header_displ(struct perf_hpp *hpp) 345{ 346 return scnprintf(hpp->buf, hpp->size, "Displ."); 347} 348 349static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused) 350{ 351 return 6; 352} 353 354static int hpp__entry_displ(struct perf_hpp *hpp, 355 struct hist_entry *he) 356{ 357 struct hist_entry *pair = hist_entry__next_pair(he); 358 long displacement = pair ? pair->position - he->position : 0; 359 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; 360 char buf[32] = " "; 361 362 if (displacement) 363 scnprintf(buf, sizeof(buf), "%+4ld", displacement); 364 365 return scnprintf(hpp->buf, hpp->size, fmt, buf); 366} 367 368static int hpp__header_formula(struct perf_hpp *hpp) 369{ 370 const char *fmt = symbol_conf.field_sep ? "%s" : "%70s"; 371 372 return scnprintf(hpp->buf, hpp->size, fmt, "Formula"); 373} 374 375static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused) 376{ 377 return 70; 378} 379 380static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he) 381{ 382 const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s"; 383 char buf[96] = " "; 384 385 perf_diff__formula(buf, sizeof(buf), he); 386 return scnprintf(hpp->buf, hpp->size, fmt, buf); 387} 388 389#define HPP__COLOR_PRINT_FNS(_name) \ 390 .header = hpp__header_ ## _name, \ 391 .width = hpp__width_ ## _name, \ 392 .color = hpp__color_ ## _name, \ 393 .entry = hpp__entry_ ## _name 394 395#define HPP__PRINT_FNS(_name) \ 396 .header = hpp__header_ ## _name, \ 397 .width = hpp__width_ ## _name, \ 398 .entry = hpp__entry_ ## _name 399 400struct perf_hpp_fmt perf_hpp__format[] = { 401 { .cond = false, HPP__COLOR_PRINT_FNS(baseline) }, 402 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, 403 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, 404 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, 405 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) }, 406 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) }, 407 { .cond = false, HPP__PRINT_FNS(samples) }, 408 { .cond = false, HPP__PRINT_FNS(period) }, 409 { .cond = false, HPP__PRINT_FNS(period_baseline) }, 410 { .cond = false, HPP__PRINT_FNS(delta) }, 411 { .cond = false, HPP__PRINT_FNS(ratio) }, 412 { .cond = false, HPP__PRINT_FNS(wdiff) }, 413 { .cond = false, HPP__PRINT_FNS(displ) }, 414 { .cond = false, HPP__PRINT_FNS(formula) } 415}; 416 417#undef HPP__COLOR_PRINT_FNS 418#undef HPP__PRINT_FNS 419 420void perf_hpp__init(void) 421{ 422 if (symbol_conf.show_cpu_utilization) { 423 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; 424 perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true; 425 426 if (perf_guest) { 427 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true; 428 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true; 429 } 430 } 431 432 if (symbol_conf.show_nr_samples) 433 perf_hpp__format[PERF_HPP__SAMPLES].cond = true; 434 435 if (symbol_conf.show_total_period) 436 perf_hpp__format[PERF_HPP__PERIOD].cond = true; 437} 438 439void perf_hpp__column_enable(unsigned col, bool enable) 440{ 441 BUG_ON(col >= PERF_HPP__MAX_INDEX); 442 perf_hpp__format[col].cond = enable; 443} 444 445static inline void advance_hpp(struct perf_hpp *hpp, int inc) 446{ 447 hpp->buf += inc; 448 hpp->size -= inc; 449} 450 451int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, 452 bool color) 453{ 454 const char *sep = symbol_conf.field_sep; 455 char *start = hpp->buf; 456 int i, ret; 457 bool first = true; 458 459 if (symbol_conf.exclude_other && !he->parent) 460 return 0; 461 462 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 463 if (!perf_hpp__format[i].cond) 464 continue; 465 466 if (!sep || !first) { 467 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); 468 advance_hpp(hpp, ret); 469 first = false; 470 } 471 472 if (color && perf_hpp__format[i].color) 473 ret = perf_hpp__format[i].color(hpp, he); 474 else 475 ret = perf_hpp__format[i].entry(hpp, he); 476 477 advance_hpp(hpp, ret); 478 } 479 480 return hpp->buf - start; 481} 482 483int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size, 484 struct hists *hists) 485{ 486 const char *sep = symbol_conf.field_sep; 487 struct sort_entry *se; 488 int ret = 0; 489 490 list_for_each_entry(se, &hist_entry__sort_list, list) { 491 if (se->elide) 492 continue; 493 494 ret += scnprintf(s + ret, size - ret, "%s", sep ?: " "); 495 ret += se->se_snprintf(he, s + ret, size - ret, 496 hists__col_len(hists, se->se_width_idx)); 497 } 498 499 return ret; 500} 501 502/* 503 * See hists__fprintf to match the column widths 504 */ 505unsigned int hists__sort_list_width(struct hists *hists) 506{ 507 struct sort_entry *se; 508 int i, ret = 0; 509 510 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 511 if (!perf_hpp__format[i].cond) 512 continue; 513 if (i) 514 ret += 2; 515 516 ret += perf_hpp__format[i].width(NULL); 517 } 518 519 list_for_each_entry(se, &hist_entry__sort_list, list) 520 if (!se->elide) 521 ret += 2 + hists__col_len(hists, se->se_width_idx); 522 523 if (verbose) /* Addr + origin */ 524 ret += 3 + BITS_PER_LONG / 4; 525 526 return ret; 527}