diff options
Diffstat (limited to 'tools/perf/ui/browsers/hists.c')
| -rw-r--r-- | tools/perf/ui/browsers/hists.c | 133 |
1 files changed, 99 insertions, 34 deletions
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 413bd62eedb1..a21f40bebbac 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
| @@ -24,9 +24,12 @@ struct hist_browser { | |||
| 24 | struct hist_entry *he_selection; | 24 | struct hist_entry *he_selection; |
| 25 | struct map_symbol *selection; | 25 | struct map_symbol *selection; |
| 26 | int print_seq; | 26 | int print_seq; |
| 27 | bool show_dso; | ||
| 27 | bool has_symbols; | 28 | bool has_symbols; |
| 28 | }; | 29 | }; |
| 29 | 30 | ||
| 31 | extern void hist_browser__init_hpp(void); | ||
| 32 | |||
| 30 | static int hists__browser_title(struct hists *hists, char *bf, size_t size, | 33 | static int hists__browser_title(struct hists *hists, char *bf, size_t size, |
| 31 | const char *ev_name); | 34 | const char *ev_name); |
| 32 | 35 | ||
| @@ -376,12 +379,19 @@ out: | |||
| 376 | } | 379 | } |
| 377 | 380 | ||
| 378 | static char *callchain_list__sym_name(struct callchain_list *cl, | 381 | static char *callchain_list__sym_name(struct callchain_list *cl, |
| 379 | char *bf, size_t bfsize) | 382 | char *bf, size_t bfsize, bool show_dso) |
| 380 | { | 383 | { |
| 384 | int printed; | ||
| 385 | |||
| 381 | if (cl->ms.sym) | 386 | if (cl->ms.sym) |
| 382 | return cl->ms.sym->name; | 387 | printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); |
| 388 | else | ||
| 389 | printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); | ||
| 390 | |||
| 391 | if (show_dso) | ||
| 392 | scnprintf(bf + printed, bfsize - printed, " %s", | ||
| 393 | cl->ms.map ? cl->ms.map->dso->short_name : "unknown"); | ||
| 383 | 394 | ||
| 384 | snprintf(bf, bfsize, "%#" PRIx64, cl->ip); | ||
| 385 | return bf; | 395 | return bf; |
| 386 | } | 396 | } |
| 387 | 397 | ||
| @@ -417,7 +427,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse | |||
| 417 | remaining -= cumul; | 427 | remaining -= cumul; |
| 418 | 428 | ||
| 419 | list_for_each_entry(chain, &child->val, list) { | 429 | list_for_each_entry(chain, &child->val, list) { |
| 420 | char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str; | 430 | char bf[1024], *alloc_str; |
| 421 | const char *str; | 431 | const char *str; |
| 422 | int color; | 432 | int color; |
| 423 | bool was_first = first; | 433 | bool was_first = first; |
| @@ -434,7 +444,8 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse | |||
| 434 | } | 444 | } |
| 435 | 445 | ||
| 436 | alloc_str = NULL; | 446 | alloc_str = NULL; |
| 437 | str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); | 447 | str = callchain_list__sym_name(chain, bf, sizeof(bf), |
| 448 | browser->show_dso); | ||
| 438 | if (was_first) { | 449 | if (was_first) { |
| 439 | double percent = cumul * 100.0 / new_total; | 450 | double percent = cumul * 100.0 / new_total; |
| 440 | 451 | ||
| @@ -493,7 +504,7 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, | |||
| 493 | char folded_sign = ' '; | 504 | char folded_sign = ' '; |
| 494 | 505 | ||
| 495 | list_for_each_entry(chain, &node->val, list) { | 506 | list_for_each_entry(chain, &node->val, list) { |
| 496 | char ipstr[BITS_PER_LONG / 4 + 1], *s; | 507 | char bf[1024], *s; |
| 497 | int color; | 508 | int color; |
| 498 | 509 | ||
| 499 | folded_sign = callchain_list__folded(chain); | 510 | folded_sign = callchain_list__folded(chain); |
| @@ -510,7 +521,8 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, | |||
| 510 | *is_current_entry = true; | 521 | *is_current_entry = true; |
| 511 | } | 522 | } |
| 512 | 523 | ||
| 513 | s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); | 524 | s = callchain_list__sym_name(chain, bf, sizeof(bf), |
| 525 | browser->show_dso); | ||
| 514 | ui_browser__gotorc(&browser->b, row, 0); | 526 | ui_browser__gotorc(&browser->b, row, 0); |
| 515 | ui_browser__set_color(&browser->b, color); | 527 | ui_browser__set_color(&browser->b, color); |
| 516 | slsmg_write_nstring(" ", offset); | 528 | slsmg_write_nstring(" ", offset); |
| @@ -553,14 +565,47 @@ static int hist_browser__show_callchain(struct hist_browser *browser, | |||
| 553 | return row - first_row; | 565 | return row - first_row; |
| 554 | } | 566 | } |
| 555 | 567 | ||
| 568 | #define HPP__COLOR_FN(_name, _field) \ | ||
| 569 | static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ | ||
| 570 | struct hist_entry *he) \ | ||
| 571 | { \ | ||
| 572 | double percent = 100.0 * he->_field / hpp->total_period; \ | ||
| 573 | *(double *)hpp->ptr = percent; \ | ||
| 574 | return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \ | ||
| 575 | } | ||
| 576 | |||
| 577 | HPP__COLOR_FN(overhead, period) | ||
| 578 | HPP__COLOR_FN(overhead_sys, period_sys) | ||
| 579 | HPP__COLOR_FN(overhead_us, period_us) | ||
| 580 | HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) | ||
| 581 | HPP__COLOR_FN(overhead_guest_us, period_guest_us) | ||
| 582 | |||
| 583 | #undef HPP__COLOR_FN | ||
| 584 | |||
| 585 | void hist_browser__init_hpp(void) | ||
| 586 | { | ||
| 587 | perf_hpp__init(false, false); | ||
| 588 | |||
| 589 | perf_hpp__format[PERF_HPP__OVERHEAD].color = | ||
| 590 | hist_browser__hpp_color_overhead; | ||
| 591 | perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = | ||
| 592 | hist_browser__hpp_color_overhead_sys; | ||
| 593 | perf_hpp__format[PERF_HPP__OVERHEAD_US].color = | ||
| 594 | hist_browser__hpp_color_overhead_us; | ||
| 595 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = | ||
| 596 | hist_browser__hpp_color_overhead_guest_sys; | ||
| 597 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = | ||
| 598 | hist_browser__hpp_color_overhead_guest_us; | ||
| 599 | } | ||
| 600 | |||
| 556 | static int hist_browser__show_entry(struct hist_browser *browser, | 601 | static int hist_browser__show_entry(struct hist_browser *browser, |
| 557 | struct hist_entry *entry, | 602 | struct hist_entry *entry, |
| 558 | unsigned short row) | 603 | unsigned short row) |
| 559 | { | 604 | { |
| 560 | char s[256]; | 605 | char s[256]; |
| 561 | double percent; | 606 | double percent; |
| 562 | int printed = 0; | 607 | int i, printed = 0; |
| 563 | int width = browser->b.width - 6; /* The percentage */ | 608 | int width = browser->b.width; |
| 564 | char folded_sign = ' '; | 609 | char folded_sign = ' '; |
| 565 | bool current_entry = ui_browser__is_current_entry(&browser->b, row); | 610 | bool current_entry = ui_browser__is_current_entry(&browser->b, row); |
| 566 | off_t row_offset = entry->row_offset; | 611 | off_t row_offset = entry->row_offset; |
| @@ -576,35 +621,50 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
| 576 | } | 621 | } |
| 577 | 622 | ||
| 578 | if (row_offset == 0) { | 623 | if (row_offset == 0) { |
| 579 | hist_entry__snprintf(entry, s, sizeof(s), browser->hists); | 624 | struct perf_hpp hpp = { |
| 580 | percent = (entry->period * 100.0) / browser->hists->stats.total_period; | 625 | .buf = s, |
| 626 | .size = sizeof(s), | ||
| 627 | .total_period = browser->hists->stats.total_period, | ||
| 628 | }; | ||
| 581 | 629 | ||
| 582 | ui_browser__set_percent_color(&browser->b, percent, current_entry); | ||
| 583 | ui_browser__gotorc(&browser->b, row, 0); | 630 | ui_browser__gotorc(&browser->b, row, 0); |
| 584 | if (symbol_conf.use_callchain) { | ||
| 585 | slsmg_printf("%c ", folded_sign); | ||
| 586 | width -= 2; | ||
| 587 | } | ||
| 588 | 631 | ||
| 589 | slsmg_printf(" %5.2f%%", percent); | 632 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
| 633 | if (!perf_hpp__format[i].cond) | ||
| 634 | continue; | ||
| 590 | 635 | ||
| 591 | /* The scroll bar isn't being used */ | 636 | if (i) { |
| 592 | if (!browser->b.navkeypressed) | 637 | slsmg_printf(" "); |
| 593 | width += 1; | 638 | width -= 2; |
| 639 | } | ||
| 594 | 640 | ||
| 595 | if (!current_entry || !browser->b.navkeypressed) | 641 | if (perf_hpp__format[i].color) { |
| 596 | ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); | 642 | hpp.ptr = &percent; |
| 643 | /* It will set percent for us. See HPP__COLOR_FN above. */ | ||
| 644 | width -= perf_hpp__format[i].color(&hpp, entry); | ||
| 597 | 645 | ||
| 598 | if (symbol_conf.show_nr_samples) { | 646 | ui_browser__set_percent_color(&browser->b, percent, current_entry); |
| 599 | slsmg_printf(" %11u", entry->nr_events); | 647 | |
| 600 | width -= 12; | 648 | if (i == 0 && symbol_conf.use_callchain) { |
| 601 | } | 649 | slsmg_printf("%c ", folded_sign); |
| 650 | width -= 2; | ||
| 651 | } | ||
| 652 | |||
| 653 | slsmg_printf("%s", s); | ||
| 602 | 654 | ||
| 603 | if (symbol_conf.show_total_period) { | 655 | if (!current_entry || !browser->b.navkeypressed) |
| 604 | slsmg_printf(" %12" PRIu64, entry->period); | 656 | ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); |
| 605 | width -= 13; | 657 | } else { |
| 658 | width -= perf_hpp__format[i].entry(&hpp, entry); | ||
| 659 | slsmg_printf("%s", s); | ||
| 660 | } | ||
| 606 | } | 661 | } |
| 607 | 662 | ||
| 663 | /* The scroll bar isn't being used */ | ||
| 664 | if (!browser->b.navkeypressed) | ||
| 665 | width += 1; | ||
| 666 | |||
| 667 | hist_entry__sort_snprintf(entry, s, sizeof(s), browser->hists); | ||
| 608 | slsmg_write_nstring(s, width); | 668 | slsmg_write_nstring(s, width); |
| 609 | ++row; | 669 | ++row; |
| 610 | ++printed; | 670 | ++printed; |
| @@ -830,7 +890,7 @@ static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *bro | |||
| 830 | remaining -= cumul; | 890 | remaining -= cumul; |
| 831 | 891 | ||
| 832 | list_for_each_entry(chain, &child->val, list) { | 892 | list_for_each_entry(chain, &child->val, list) { |
| 833 | char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str; | 893 | char bf[1024], *alloc_str; |
| 834 | const char *str; | 894 | const char *str; |
| 835 | bool was_first = first; | 895 | bool was_first = first; |
| 836 | 896 | ||
| @@ -842,7 +902,8 @@ static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *bro | |||
| 842 | folded_sign = callchain_list__folded(chain); | 902 | folded_sign = callchain_list__folded(chain); |
| 843 | 903 | ||
| 844 | alloc_str = NULL; | 904 | alloc_str = NULL; |
| 845 | str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); | 905 | str = callchain_list__sym_name(chain, bf, sizeof(bf), |
| 906 | browser->show_dso); | ||
| 846 | if (was_first) { | 907 | if (was_first) { |
| 847 | double percent = cumul * 100.0 / new_total; | 908 | double percent = cumul * 100.0 / new_total; |
| 848 | 909 | ||
| @@ -880,10 +941,10 @@ static int hist_browser__fprintf_callchain_node(struct hist_browser *browser, | |||
| 880 | int printed = 0; | 941 | int printed = 0; |
| 881 | 942 | ||
| 882 | list_for_each_entry(chain, &node->val, list) { | 943 | list_for_each_entry(chain, &node->val, list) { |
| 883 | char ipstr[BITS_PER_LONG / 4 + 1], *s; | 944 | char bf[1024], *s; |
| 884 | 945 | ||
| 885 | folded_sign = callchain_list__folded(chain); | 946 | folded_sign = callchain_list__folded(chain); |
| 886 | s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); | 947 | s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso); |
| 887 | printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s); | 948 | printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s); |
| 888 | } | 949 | } |
| 889 | 950 | ||
| @@ -920,7 +981,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, | |||
| 920 | if (symbol_conf.use_callchain) | 981 | if (symbol_conf.use_callchain) |
| 921 | folded_sign = hist_entry__folded(he); | 982 | folded_sign = hist_entry__folded(he); |
| 922 | 983 | ||
| 923 | hist_entry__snprintf(he, s, sizeof(s), browser->hists); | 984 | hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists); |
| 924 | percent = (he->period * 100.0) / browser->hists->stats.total_period; | 985 | percent = (he->period * 100.0) / browser->hists->stats.total_period; |
| 925 | 986 | ||
| 926 | if (symbol_conf.use_callchain) | 987 | if (symbol_conf.use_callchain) |
| @@ -1133,6 +1194,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
| 1133 | continue; | 1194 | continue; |
| 1134 | case 'd': | 1195 | case 'd': |
| 1135 | goto zoom_dso; | 1196 | goto zoom_dso; |
| 1197 | case 'V': | ||
| 1198 | browser->show_dso = !browser->show_dso; | ||
| 1199 | continue; | ||
| 1136 | case 't': | 1200 | case 't': |
| 1137 | goto zoom_thread; | 1201 | goto zoom_thread; |
| 1138 | case '/': | 1202 | case '/': |
| @@ -1164,6 +1228,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
| 1164 | "d Zoom into current DSO\n" | 1228 | "d Zoom into current DSO\n" |
| 1165 | "t Zoom into current Thread\n" | 1229 | "t Zoom into current Thread\n" |
| 1166 | "P Print histograms to perf.hist.N\n" | 1230 | "P Print histograms to perf.hist.N\n" |
| 1231 | "V Verbose (DSO names in callchains, etc)\n" | ||
| 1167 | "/ Filter symbol by name"); | 1232 | "/ Filter symbol by name"); |
| 1168 | continue; | 1233 | continue; |
| 1169 | case K_ENTER: | 1234 | case K_ENTER: |
