diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-09-09 04:39:14 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-09-09 04:39:14 -0400 |
commit | d5cb2aef4fda355fbafe8db4f425b73ea94d2019 (patch) | |
tree | f6812e5248557bd16803f787e0cbc9d57ab60133 | |
parent | ef34eb4da3eb62a1511592adf7c76d74faca0b14 (diff) | |
parent | 6c7f631261064762a8ba1ee34fc2b76d117ef3fa (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
* Don't pass const char pointers to basename, so that we can unconditionally
use libgen.h and thus avoid ifdef BIONIC lines, from David Ahern
* Fix assert/BUG_ON when NDEBUG is defined, from Irina Tirdea.
* Refactor hist formatting so that it can be reused with the GTK browser,
From Namhyung Kim
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/perf/Makefile | 2 | ||||
-rw-r--r-- | tools/perf/bench/sched-pipe.c | 6 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 1 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 96 | ||||
-rw-r--r-- | tools/perf/ui/gtk/browser.c | 101 | ||||
-rw-r--r-- | tools/perf/ui/gtk/gtk.h | 1 | ||||
-rw-r--r-- | tools/perf/ui/gtk/setup.c | 1 | ||||
-rw-r--r-- | tools/perf/ui/hist.c | 389 | ||||
-rw-r--r-- | tools/perf/ui/setup.c | 8 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 239 | ||||
-rw-r--r-- | tools/perf/ui/tui/setup.c | 4 | ||||
-rw-r--r-- | tools/perf/util/annotate.c | 9 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 33 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 37 | ||||
-rw-r--r-- | tools/perf/util/include/linux/kernel.h | 4 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 12 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 2 |
17 files changed, 665 insertions, 280 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3eda4921573..e4b2e8f2606 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -403,7 +403,9 @@ LIB_OBJS += $(OUTPUT)util/cgroup.o | |||
403 | LIB_OBJS += $(OUTPUT)util/target.o | 403 | LIB_OBJS += $(OUTPUT)util/target.o |
404 | LIB_OBJS += $(OUTPUT)util/rblist.o | 404 | LIB_OBJS += $(OUTPUT)util/rblist.o |
405 | LIB_OBJS += $(OUTPUT)util/intlist.o | 405 | LIB_OBJS += $(OUTPUT)util/intlist.o |
406 | |||
406 | LIB_OBJS += $(OUTPUT)ui/helpline.o | 407 | LIB_OBJS += $(OUTPUT)ui/helpline.o |
408 | LIB_OBJS += $(OUTPUT)ui/hist.o | ||
407 | LIB_OBJS += $(OUTPUT)ui/stdio/hist.o | 409 | LIB_OBJS += $(OUTPUT)ui/stdio/hist.o |
408 | 410 | ||
409 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o | 411 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o |
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index 0c7454f8b8a..15911e9c587 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c | |||
@@ -56,13 +56,13 @@ int bench_sched_pipe(int argc, const char **argv, | |||
56 | * causes error in building environment for perf | 56 | * causes error in building environment for perf |
57 | */ | 57 | */ |
58 | int __used ret, wait_stat; | 58 | int __used ret, wait_stat; |
59 | pid_t pid, retpid; | 59 | pid_t pid, retpid __used; |
60 | 60 | ||
61 | argc = parse_options(argc, argv, options, | 61 | argc = parse_options(argc, argv, options, |
62 | bench_sched_pipe_usage, 0); | 62 | bench_sched_pipe_usage, 0); |
63 | 63 | ||
64 | assert(!pipe(pipe_1)); | 64 | BUG_ON(pipe(pipe_1)); |
65 | assert(!pipe(pipe_2)); | 65 | BUG_ON(pipe(pipe_2)); |
66 | 66 | ||
67 | pid = fork(); | 67 | pid = fork(); |
68 | assert(pid >= 0); | 68 | assert(pid >= 0); |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index e9933fdd256..c4c6d76b70e 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -264,6 +264,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __used) | |||
264 | if (symbol__init() < 0) | 264 | if (symbol__init() < 0) |
265 | return -1; | 265 | return -1; |
266 | 266 | ||
267 | perf_hpp__init(true, show_displacement); | ||
267 | setup_sorting(diff_usage, options); | 268 | setup_sorting(diff_usage, options); |
268 | setup_pager(); | 269 | setup_pager(); |
269 | 270 | ||
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 81bd8c2af73..5a5739bbe6a 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -28,6 +28,8 @@ struct hist_browser { | |||
28 | bool has_symbols; | 28 | bool has_symbols; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | extern void hist_browser__init_hpp(void); | ||
32 | |||
31 | 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, |
32 | const char *ev_name); | 34 | const char *ev_name); |
33 | 35 | ||
@@ -563,14 +565,47 @@ static int hist_browser__show_callchain(struct hist_browser *browser, | |||
563 | return row - first_row; | 565 | return row - first_row; |
564 | } | 566 | } |
565 | 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, "%5.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 | |||
566 | static int hist_browser__show_entry(struct hist_browser *browser, | 601 | static int hist_browser__show_entry(struct hist_browser *browser, |
567 | struct hist_entry *entry, | 602 | struct hist_entry *entry, |
568 | unsigned short row) | 603 | unsigned short row) |
569 | { | 604 | { |
570 | char s[256]; | 605 | char s[256]; |
571 | double percent; | 606 | double percent; |
572 | int printed = 0; | 607 | int i, printed = 0; |
573 | int width = browser->b.width - 6; /* The percentage */ | 608 | int width = browser->b.width - 1; |
574 | char folded_sign = ' '; | 609 | char folded_sign = ' '; |
575 | bool current_entry = ui_browser__is_current_entry(&browser->b, row); | 610 | bool current_entry = ui_browser__is_current_entry(&browser->b, row); |
576 | off_t row_offset = entry->row_offset; | 611 | off_t row_offset = entry->row_offset; |
@@ -586,35 +621,50 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
586 | } | 621 | } |
587 | 622 | ||
588 | if (row_offset == 0) { | 623 | if (row_offset == 0) { |
589 | hist_entry__sort_snprintf(entry, s, sizeof(s), browser->hists); | 624 | struct perf_hpp hpp = { |
590 | 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 | }; | ||
591 | 629 | ||
592 | ui_browser__set_percent_color(&browser->b, percent, current_entry); | 630 | ui_browser__gotorc(&browser->b, row, 1); |
593 | ui_browser__gotorc(&browser->b, row, 0); | ||
594 | if (symbol_conf.use_callchain) { | ||
595 | slsmg_printf("%c ", folded_sign); | ||
596 | width -= 2; | ||
597 | } | ||
598 | 631 | ||
599 | slsmg_printf(" %5.2f%%", percent); | 632 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
633 | if (!perf_hpp__format[i].cond) | ||
634 | continue; | ||
600 | 635 | ||
601 | /* The scroll bar isn't being used */ | 636 | if (i) { |
602 | if (!browser->b.navkeypressed) | 637 | slsmg_printf(" "); |
603 | width += 1; | 638 | width -= 2; |
639 | } | ||
604 | 640 | ||
605 | if (!current_entry || !browser->b.navkeypressed) | 641 | if (perf_hpp__format[i].color) { |
606 | 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); | ||
607 | 645 | ||
608 | if (symbol_conf.show_nr_samples) { | 646 | ui_browser__set_percent_color(&browser->b, percent, current_entry); |
609 | slsmg_printf(" %11u", entry->nr_events); | 647 | |
610 | width -= 12; | 648 | if (i == 0 && symbol_conf.use_callchain) { |
611 | } | 649 | slsmg_printf("%c ", folded_sign); |
650 | width -= 2; | ||
651 | } | ||
652 | |||
653 | slsmg_printf("%s", s); | ||
612 | 654 | ||
613 | if (symbol_conf.show_total_period) { | 655 | if (!current_entry || !browser->b.navkeypressed) |
614 | slsmg_printf(" %12" PRIu64, entry->period); | 656 | ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); |
615 | width -= 13; | 657 | } else { |
658 | width -= perf_hpp__format[i].entry(&hpp, entry); | ||
659 | slsmg_printf("%s", s); | ||
660 | } | ||
616 | } | 661 | } |
617 | 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); | ||
618 | slsmg_write_nstring(s, width); | 668 | slsmg_write_nstring(s, width); |
619 | ++row; | 669 | ++row; |
620 | ++printed; | 670 | ++printed; |
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 26b5b652a8c..3c16ab50e0f 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c | |||
@@ -36,6 +36,57 @@ static void perf_gtk__resize_window(GtkWidget *window) | |||
36 | gtk_window_resize(GTK_WINDOW(window), width, height); | 36 | gtk_window_resize(GTK_WINDOW(window), width, height); |
37 | } | 37 | } |
38 | 38 | ||
39 | static const char *perf_gtk__get_percent_color(double percent) | ||
40 | { | ||
41 | if (percent >= MIN_RED) | ||
42 | return "<span fgcolor='red'>"; | ||
43 | if (percent >= MIN_GREEN) | ||
44 | return "<span fgcolor='dark green'>"; | ||
45 | return NULL; | ||
46 | } | ||
47 | |||
48 | #define HPP__COLOR_FN(_name, _field) \ | ||
49 | static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ | ||
50 | struct hist_entry *he) \ | ||
51 | { \ | ||
52 | double percent = 100.0 * he->_field / hpp->total_period; \ | ||
53 | const char *markup; \ | ||
54 | int ret = 0; \ | ||
55 | \ | ||
56 | markup = perf_gtk__get_percent_color(percent); \ | ||
57 | if (markup) \ | ||
58 | ret += scnprintf(hpp->buf, hpp->size, "%s", markup); \ | ||
59 | ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%5.2f%%", percent); \ | ||
60 | if (markup) \ | ||
61 | ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>"); \ | ||
62 | \ | ||
63 | return ret; \ | ||
64 | } | ||
65 | |||
66 | HPP__COLOR_FN(overhead, period) | ||
67 | HPP__COLOR_FN(overhead_sys, period_sys) | ||
68 | HPP__COLOR_FN(overhead_us, period_us) | ||
69 | HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) | ||
70 | HPP__COLOR_FN(overhead_guest_us, period_guest_us) | ||
71 | |||
72 | #undef HPP__COLOR_FN | ||
73 | |||
74 | void perf_gtk__init_hpp(void) | ||
75 | { | ||
76 | perf_hpp__init(false, false); | ||
77 | |||
78 | perf_hpp__format[PERF_HPP__OVERHEAD].color = | ||
79 | perf_gtk__hpp_color_overhead; | ||
80 | perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = | ||
81 | perf_gtk__hpp_color_overhead_sys; | ||
82 | perf_hpp__format[PERF_HPP__OVERHEAD_US].color = | ||
83 | perf_gtk__hpp_color_overhead_us; | ||
84 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = | ||
85 | perf_gtk__hpp_color_overhead_guest_sys; | ||
86 | perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = | ||
87 | perf_gtk__hpp_color_overhead_guest_us; | ||
88 | } | ||
89 | |||
39 | static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | 90 | static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) |
40 | { | 91 | { |
41 | GType col_types[MAX_COLUMNS]; | 92 | GType col_types[MAX_COLUMNS]; |
@@ -43,15 +94,25 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | |||
43 | struct sort_entry *se; | 94 | struct sort_entry *se; |
44 | GtkListStore *store; | 95 | GtkListStore *store; |
45 | struct rb_node *nd; | 96 | struct rb_node *nd; |
46 | u64 total_period; | ||
47 | GtkWidget *view; | 97 | GtkWidget *view; |
48 | int col_idx; | 98 | int i, col_idx; |
49 | int nr_cols; | 99 | int nr_cols; |
100 | char s[512]; | ||
101 | |||
102 | struct perf_hpp hpp = { | ||
103 | .buf = s, | ||
104 | .size = sizeof(s), | ||
105 | .total_period = hists->stats.total_period, | ||
106 | }; | ||
50 | 107 | ||
51 | nr_cols = 0; | 108 | nr_cols = 0; |
52 | 109 | ||
53 | /* The percentage column */ | 110 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
54 | col_types[nr_cols++] = G_TYPE_STRING; | 111 | if (!perf_hpp__format[i].cond) |
112 | continue; | ||
113 | |||
114 | col_types[nr_cols++] = G_TYPE_STRING; | ||
115 | } | ||
55 | 116 | ||
56 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 117 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
57 | if (se->elide) | 118 | if (se->elide) |
@@ -68,11 +129,17 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | |||
68 | 129 | ||
69 | col_idx = 0; | 130 | col_idx = 0; |
70 | 131 | ||
71 | /* The percentage column */ | 132 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
72 | gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), | 133 | if (!perf_hpp__format[i].cond) |
73 | -1, "Overhead (%)", | 134 | continue; |
74 | renderer, "text", | 135 | |
75 | col_idx++, NULL); | 136 | perf_hpp__format[i].header(&hpp); |
137 | |||
138 | gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), | ||
139 | -1, s, | ||
140 | renderer, "markup", | ||
141 | col_idx++, NULL); | ||
142 | } | ||
76 | 143 | ||
77 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 144 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
78 | if (se->elide) | 145 | if (se->elide) |
@@ -88,13 +155,9 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | |||
88 | 155 | ||
89 | g_object_unref(GTK_TREE_MODEL(store)); | 156 | g_object_unref(GTK_TREE_MODEL(store)); |
90 | 157 | ||
91 | total_period = hists->stats.total_period; | ||
92 | |||
93 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { | 158 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { |
94 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 159 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
95 | GtkTreeIter iter; | 160 | GtkTreeIter iter; |
96 | double percent; | ||
97 | char s[512]; | ||
98 | 161 | ||
99 | if (h->filtered) | 162 | if (h->filtered) |
100 | continue; | 163 | continue; |
@@ -103,11 +166,17 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) | |||
103 | 166 | ||
104 | col_idx = 0; | 167 | col_idx = 0; |
105 | 168 | ||
106 | percent = (h->period * 100.0) / total_period; | 169 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
170 | if (!perf_hpp__format[i].cond) | ||
171 | continue; | ||
107 | 172 | ||
108 | snprintf(s, ARRAY_SIZE(s), "%.2f", percent); | 173 | if (perf_hpp__format[i].color) |
174 | perf_hpp__format[i].color(&hpp, h); | ||
175 | else | ||
176 | perf_hpp__format[i].entry(&hpp, h); | ||
109 | 177 | ||
110 | gtk_list_store_set(store, &iter, col_idx++, s, -1); | 178 | gtk_list_store_set(store, &iter, col_idx++, s, -1); |
179 | } | ||
111 | 180 | ||
112 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 181 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
113 | if (se->elide) | 182 | if (se->elide) |
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index 793cb6116dd..687af0bba18 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h | |||
@@ -30,6 +30,7 @@ struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window); | |||
30 | int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); | 30 | int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); |
31 | 31 | ||
32 | void perf_gtk__init_helpline(void); | 32 | void perf_gtk__init_helpline(void); |
33 | void perf_gtk__init_hpp(void); | ||
33 | 34 | ||
34 | #ifndef HAVE_GTK_INFO_BAR | 35 | #ifndef HAVE_GTK_INFO_BAR |
35 | static inline GtkWidget *perf_gtk__setup_info_bar(void) | 36 | static inline GtkWidget *perf_gtk__setup_info_bar(void) |
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c index ec1ee26b485..26429437e19 100644 --- a/tools/perf/ui/gtk/setup.c +++ b/tools/perf/ui/gtk/setup.c | |||
@@ -8,6 +8,7 @@ int perf_gtk__init(void) | |||
8 | { | 8 | { |
9 | perf_error__register(&perf_gtk_eops); | 9 | perf_error__register(&perf_gtk_eops); |
10 | perf_gtk__init_helpline(); | 10 | perf_gtk__init_helpline(); |
11 | perf_gtk__init_hpp(); | ||
11 | return gtk_init_check(NULL, NULL) ? 0 : -1; | 12 | return gtk_init_check(NULL, NULL) ? 0 : -1; |
12 | } | 13 | } |
13 | 14 | ||
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c new file mode 100644 index 00000000000..031b349a3f8 --- /dev/null +++ b/tools/perf/ui/hist.c | |||
@@ -0,0 +1,389 @@ | |||
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 | { | ||
11 | const char *fmt = hpp->ptr ? "Baseline" : "Overhead"; | ||
12 | |||
13 | return scnprintf(hpp->buf, hpp->size, fmt); | ||
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; | ||
42 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%%"; | ||
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 | |||
55 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
56 | } | ||
57 | |||
58 | static int hpp__header_overhead_sys(struct perf_hpp *hpp) | ||
59 | { | ||
60 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6s"; | ||
61 | |||
62 | return scnprintf(hpp->buf, hpp->size, fmt, "sys"); | ||
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; | ||
79 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%5.2f%%"; | ||
80 | |||
81 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
82 | } | ||
83 | |||
84 | static int hpp__header_overhead_us(struct perf_hpp *hpp) | ||
85 | { | ||
86 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6s"; | ||
87 | |||
88 | return scnprintf(hpp->buf, hpp->size, fmt, "user"); | ||
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; | ||
105 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%5.2f%%"; | ||
106 | |||
107 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
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; | ||
131 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%% "; | ||
132 | |||
133 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
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; | ||
157 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%% "; | ||
158 | |||
159 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | ||
160 | } | ||
161 | |||
162 | static int hpp__header_samples(struct perf_hpp *hpp) | ||
163 | { | ||
164 | const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; | ||
165 | |||
166 | return scnprintf(hpp->buf, hpp->size, fmt, "Samples"); | ||
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 | { | ||
176 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; | ||
177 | |||
178 | return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events); | ||
179 | } | ||
180 | |||
181 | static int hpp__header_period(struct perf_hpp *hpp) | ||
182 | { | ||
183 | const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; | ||
184 | |||
185 | return scnprintf(hpp->buf, hpp->size, fmt, "Period"); | ||
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 | { | ||
195 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; | ||
196 | |||
197 | return scnprintf(hpp->buf, hpp->size, fmt, he->period); | ||
198 | } | ||
199 | |||
200 | static int hpp__header_delta(struct perf_hpp *hpp) | ||
201 | { | ||
202 | const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; | ||
203 | |||
204 | return scnprintf(hpp->buf, hpp->size, fmt, "Delta"); | ||
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; | ||
218 | const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; | ||
219 | char buf[32] = " "; | ||
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; | ||
230 | if (fabs(diff) >= 0.01) | ||
231 | scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); | ||
232 | |||
233 | return scnprintf(hpp->buf, hpp->size, fmt, buf); | ||
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 | { | ||
248 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; | ||
249 | char buf[32] = " "; | ||
250 | |||
251 | if (hpp->displacement) | ||
252 | scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement); | ||
253 | |||
254 | return scnprintf(hpp->buf, hpp->size, fmt, buf); | ||
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 | } | ||
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 | } | ||
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c index c7820e56966..bd7d460f844 100644 --- a/tools/perf/ui/setup.c +++ b/tools/perf/ui/setup.c | |||
@@ -1,8 +1,8 @@ | |||
1 | #include <pthread.h> | 1 | #include <pthread.h> |
2 | 2 | ||
3 | #include "../cache.h" | 3 | #include "../util/cache.h" |
4 | #include "../debug.h" | 4 | #include "../util/debug.h" |
5 | 5 | #include "../util/hist.h" | |
6 | 6 | ||
7 | pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; | 7 | pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; |
8 | 8 | ||
@@ -29,6 +29,8 @@ void setup_browser(bool fallback_to_pager) | |||
29 | use_browser = 0; | 29 | use_browser = 0; |
30 | if (fallback_to_pager) | 30 | if (fallback_to_pager) |
31 | setup_pager(); | 31 | setup_pager(); |
32 | |||
33 | perf_hpp__init(false, false); | ||
32 | break; | 34 | break; |
33 | } | 35 | } |
34 | } | 36 | } |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 9bf7e9e5a72..882461a4283 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -1,5 +1,4 @@ | |||
1 | #include <stdio.h> | 1 | #include <stdio.h> |
2 | #include <math.h> | ||
3 | 2 | ||
4 | #include "../../util/util.h" | 3 | #include "../../util/util.h" |
5 | #include "../../util/hist.h" | 4 | #include "../../util/hist.h" |
@@ -291,138 +290,6 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he, | |||
291 | return 0; | 290 | return 0; |
292 | } | 291 | } |
293 | 292 | ||
294 | static int hist_entry__period_snprintf(struct hist_entry *he, char *s, | ||
295 | size_t size, struct hists *pair_hists, | ||
296 | bool show_displacement, long displacement, | ||
297 | bool color, u64 total_period) | ||
298 | { | ||
299 | u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; | ||
300 | u64 nr_events; | ||
301 | const char *sep = symbol_conf.field_sep; | ||
302 | int ret; | ||
303 | |||
304 | if (symbol_conf.exclude_other && !he->parent) | ||
305 | return 0; | ||
306 | |||
307 | if (pair_hists) { | ||
308 | period = he->pair ? he->pair->period : 0; | ||
309 | nr_events = he->pair ? he->pair->nr_events : 0; | ||
310 | total = pair_hists->stats.total_period; | ||
311 | period_sys = he->pair ? he->pair->period_sys : 0; | ||
312 | period_us = he->pair ? he->pair->period_us : 0; | ||
313 | period_guest_sys = he->pair ? he->pair->period_guest_sys : 0; | ||
314 | period_guest_us = he->pair ? he->pair->period_guest_us : 0; | ||
315 | } else { | ||
316 | period = he->period; | ||
317 | nr_events = he->nr_events; | ||
318 | total = total_period; | ||
319 | period_sys = he->period_sys; | ||
320 | period_us = he->period_us; | ||
321 | period_guest_sys = he->period_guest_sys; | ||
322 | period_guest_us = he->period_guest_us; | ||
323 | } | ||
324 | |||
325 | if (total) { | ||
326 | if (color) | ||
327 | ret = percent_color_snprintf(s, size, | ||
328 | sep ? "%.2f" : " %6.2f%%", | ||
329 | (period * 100.0) / total); | ||
330 | else | ||
331 | ret = scnprintf(s, size, sep ? "%.2f" : " %6.2f%%", | ||
332 | (period * 100.0) / total); | ||
333 | if (symbol_conf.show_cpu_utilization) { | ||
334 | ret += percent_color_snprintf(s + ret, size - ret, | ||
335 | sep ? "%.2f" : " %6.2f%%", | ||
336 | (period_sys * 100.0) / total); | ||
337 | ret += percent_color_snprintf(s + ret, size - ret, | ||
338 | sep ? "%.2f" : " %6.2f%%", | ||
339 | (period_us * 100.0) / total); | ||
340 | if (perf_guest) { | ||
341 | ret += percent_color_snprintf(s + ret, | ||
342 | size - ret, | ||
343 | sep ? "%.2f" : " %6.2f%%", | ||
344 | (period_guest_sys * 100.0) / | ||
345 | total); | ||
346 | ret += percent_color_snprintf(s + ret, | ||
347 | size - ret, | ||
348 | sep ? "%.2f" : " %6.2f%%", | ||
349 | (period_guest_us * 100.0) / | ||
350 | total); | ||
351 | } | ||
352 | } | ||
353 | } else | ||
354 | ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period); | ||
355 | |||
356 | if (symbol_conf.show_nr_samples) { | ||
357 | if (sep) | ||
358 | ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events); | ||
359 | else | ||
360 | ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events); | ||
361 | } | ||
362 | |||
363 | if (symbol_conf.show_total_period) { | ||
364 | if (sep) | ||
365 | ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period); | ||
366 | else | ||
367 | ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period); | ||
368 | } | ||
369 | |||
370 | if (pair_hists) { | ||
371 | char bf[32]; | ||
372 | double old_percent = 0, new_percent = 0, diff; | ||
373 | |||
374 | if (total > 0) | ||
375 | old_percent = (period * 100.0) / total; | ||
376 | if (total_period > 0) | ||
377 | new_percent = (he->period * 100.0) / total_period; | ||
378 | |||
379 | diff = new_percent - old_percent; | ||
380 | |||
381 | if (fabs(diff) >= 0.01) | ||
382 | scnprintf(bf, sizeof(bf), "%+4.2F%%", diff); | ||
383 | else | ||
384 | scnprintf(bf, sizeof(bf), " "); | ||
385 | |||
386 | if (sep) | ||
387 | ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf); | ||
388 | else | ||
389 | ret += scnprintf(s + ret, size - ret, "%11.11s", bf); | ||
390 | |||
391 | if (show_displacement) { | ||
392 | if (displacement) | ||
393 | scnprintf(bf, sizeof(bf), "%+4ld", displacement); | ||
394 | else | ||
395 | scnprintf(bf, sizeof(bf), " "); | ||
396 | |||
397 | if (sep) | ||
398 | ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf); | ||
399 | else | ||
400 | ret += scnprintf(s + ret, size - ret, "%6.6s", bf); | ||
401 | } | ||
402 | } | ||
403 | |||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size, | ||
408 | struct hists *hists) | ||
409 | { | ||
410 | const char *sep = symbol_conf.field_sep; | ||
411 | struct sort_entry *se; | ||
412 | int ret = 0; | ||
413 | |||
414 | list_for_each_entry(se, &hist_entry__sort_list, list) { | ||
415 | if (se->elide) | ||
416 | continue; | ||
417 | |||
418 | ret += scnprintf(s + ret, size - ret, "%s", sep ?: " "); | ||
419 | ret += se->se_snprintf(he, s + ret, size - ret, | ||
420 | hists__col_len(hists, se->se_width_idx)); | ||
421 | } | ||
422 | |||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | static size_t hist_entry__callchain_fprintf(struct hist_entry *he, | 293 | static size_t hist_entry__callchain_fprintf(struct hist_entry *he, |
427 | struct hists *hists, | 294 | struct hists *hists, |
428 | u64 total_period, FILE *fp) | 295 | u64 total_period, FILE *fp) |
@@ -441,18 +308,23 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he, | |||
441 | 308 | ||
442 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, | 309 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, |
443 | struct hists *hists, struct hists *pair_hists, | 310 | struct hists *hists, struct hists *pair_hists, |
444 | bool show_displacement, long displacement, | 311 | long displacement, u64 total_period, FILE *fp) |
445 | u64 total_period, FILE *fp) | ||
446 | { | 312 | { |
447 | char bf[512]; | 313 | char bf[512]; |
448 | int ret; | 314 | int ret; |
315 | struct perf_hpp hpp = { | ||
316 | .buf = bf, | ||
317 | .size = size, | ||
318 | .total_period = total_period, | ||
319 | .displacement = displacement, | ||
320 | .ptr = pair_hists, | ||
321 | }; | ||
322 | bool color = !symbol_conf.field_sep; | ||
449 | 323 | ||
450 | if (size == 0 || size > sizeof(bf)) | 324 | if (size == 0 || size > sizeof(bf)) |
451 | size = sizeof(bf); | 325 | size = hpp.size = sizeof(bf); |
452 | 326 | ||
453 | ret = hist_entry__period_snprintf(he, bf, size, pair_hists, | 327 | ret = hist_entry__period_snprintf(&hpp, he, color); |
454 | show_displacement, displacement, | ||
455 | true, total_period); | ||
456 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); | 328 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); |
457 | 329 | ||
458 | ret = fprintf(fp, "%s\n", bf); | 330 | ret = fprintf(fp, "%s\n", bf); |
@@ -477,59 +349,29 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, | |||
477 | unsigned int width; | 349 | unsigned int width; |
478 | const char *sep = symbol_conf.field_sep; | 350 | const char *sep = symbol_conf.field_sep; |
479 | const char *col_width = symbol_conf.col_width_list_str; | 351 | const char *col_width = symbol_conf.col_width_list_str; |
480 | int nr_rows = 0; | 352 | int idx, nr_rows = 0; |
353 | char bf[64]; | ||
354 | struct perf_hpp dummy_hpp = { | ||
355 | .buf = bf, | ||
356 | .size = sizeof(bf), | ||
357 | .ptr = pair, | ||
358 | }; | ||
481 | 359 | ||
482 | init_rem_hits(); | 360 | init_rem_hits(); |
483 | 361 | ||
484 | if (!show_header) | 362 | if (!show_header) |
485 | goto print_entries; | 363 | goto print_entries; |
486 | 364 | ||
487 | fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); | 365 | fprintf(fp, "# "); |
488 | 366 | for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { | |
489 | if (symbol_conf.show_cpu_utilization) { | 367 | if (!perf_hpp__format[idx].cond) |
490 | if (sep) { | 368 | continue; |
491 | ret += fprintf(fp, "%csys", *sep); | ||
492 | ret += fprintf(fp, "%cus", *sep); | ||
493 | if (perf_guest) { | ||
494 | ret += fprintf(fp, "%cguest sys", *sep); | ||
495 | ret += fprintf(fp, "%cguest us", *sep); | ||
496 | } | ||
497 | } else { | ||
498 | ret += fprintf(fp, " sys "); | ||
499 | ret += fprintf(fp, " us "); | ||
500 | if (perf_guest) { | ||
501 | ret += fprintf(fp, " guest sys "); | ||
502 | ret += fprintf(fp, " guest us "); | ||
503 | } | ||
504 | } | ||
505 | } | ||
506 | |||
507 | if (symbol_conf.show_nr_samples) { | ||
508 | if (sep) | ||
509 | fprintf(fp, "%cSamples", *sep); | ||
510 | else | ||
511 | fputs(" Samples ", fp); | ||
512 | } | ||
513 | |||
514 | if (symbol_conf.show_total_period) { | ||
515 | if (sep) | ||
516 | ret += fprintf(fp, "%cPeriod", *sep); | ||
517 | else | ||
518 | ret += fprintf(fp, " Period "); | ||
519 | } | ||
520 | 369 | ||
521 | if (pair) { | 370 | if (idx) |
522 | if (sep) | 371 | fprintf(fp, "%s", sep ?: " "); |
523 | ret += fprintf(fp, "%cDelta", *sep); | ||
524 | else | ||
525 | ret += fprintf(fp, " Delta "); | ||
526 | 372 | ||
527 | if (show_displacement) { | 373 | perf_hpp__format[idx].header(&dummy_hpp); |
528 | if (sep) | 374 | fprintf(fp, "%s", bf); |
529 | ret += fprintf(fp, "%cDisplacement", *sep); | ||
530 | else | ||
531 | ret += fprintf(fp, " Displ"); | ||
532 | } | ||
533 | } | 375 | } |
534 | 376 | ||
535 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 377 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
@@ -561,18 +403,21 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, | |||
561 | if (sep) | 403 | if (sep) |
562 | goto print_entries; | 404 | goto print_entries; |
563 | 405 | ||
564 | fprintf(fp, "# ........"); | 406 | fprintf(fp, "# "); |
565 | if (symbol_conf.show_cpu_utilization) | 407 | for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { |
566 | fprintf(fp, " ....... ......."); | 408 | unsigned int i; |
567 | if (symbol_conf.show_nr_samples) | 409 | |
568 | fprintf(fp, " .........."); | 410 | if (!perf_hpp__format[idx].cond) |
569 | if (symbol_conf.show_total_period) | 411 | continue; |
570 | fprintf(fp, " ............"); | 412 | |
571 | if (pair) { | 413 | if (idx) |
572 | fprintf(fp, " .........."); | 414 | fprintf(fp, "%s", sep ?: " "); |
573 | if (show_displacement) | 415 | |
574 | fprintf(fp, " ....."); | 416 | width = perf_hpp__format[idx].width(&dummy_hpp); |
417 | for (i = 0; i < width; i++) | ||
418 | fprintf(fp, "."); | ||
575 | } | 419 | } |
420 | |||
576 | list_for_each_entry(se, &hist_entry__sort_list, list) { | 421 | list_for_each_entry(se, &hist_entry__sort_list, list) { |
577 | unsigned int i; | 422 | unsigned int i; |
578 | 423 | ||
@@ -612,8 +457,8 @@ print_entries: | |||
612 | displacement = 0; | 457 | displacement = 0; |
613 | ++position; | 458 | ++position; |
614 | } | 459 | } |
615 | ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement, | 460 | ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement, |
616 | displacement, total_period, fp); | 461 | total_period, fp); |
617 | 462 | ||
618 | if (max_rows && ++nr_rows >= max_rows) | 463 | if (max_rows && ++nr_rows >= max_rows) |
619 | goto out; | 464 | goto out; |
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 4c936e09931..4dc0887c04f 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c | |||
@@ -15,6 +15,8 @@ static volatile int ui__need_resize; | |||
15 | 15 | ||
16 | extern struct perf_error_ops perf_tui_eops; | 16 | extern struct perf_error_ops perf_tui_eops; |
17 | 17 | ||
18 | extern void hist_browser__init_hpp(void); | ||
19 | |||
18 | void ui__refresh_dimensions(bool force) | 20 | void ui__refresh_dimensions(bool force) |
19 | { | 21 | { |
20 | if (force || ui__need_resize) { | 22 | if (force || ui__need_resize) { |
@@ -124,6 +126,8 @@ int ui__init(void) | |||
124 | signal(SIGTERM, ui__signal); | 126 | signal(SIGTERM, ui__signal); |
125 | 127 | ||
126 | perf_error__register(&perf_tui_eops); | 128 | perf_error__register(&perf_tui_eops); |
129 | |||
130 | hist_browser__init_hpp(); | ||
127 | out: | 131 | out: |
128 | return err; | 132 | return err; |
129 | } | 133 | } |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 51ef69c9841..04eafd3939d 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -984,7 +984,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, | |||
984 | int context) | 984 | int context) |
985 | { | 985 | { |
986 | struct dso *dso = map->dso; | 986 | struct dso *dso = map->dso; |
987 | const char *filename = dso->long_name, *d_filename; | 987 | char *filename; |
988 | const char *d_filename; | ||
988 | struct annotation *notes = symbol__annotation(sym); | 989 | struct annotation *notes = symbol__annotation(sym); |
989 | struct disasm_line *pos, *queue = NULL; | 990 | struct disasm_line *pos, *queue = NULL; |
990 | u64 start = map__rip_2objdump(map, sym->start); | 991 | u64 start = map__rip_2objdump(map, sym->start); |
@@ -992,6 +993,10 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, | |||
992 | int more = 0; | 993 | int more = 0; |
993 | u64 len; | 994 | u64 len; |
994 | 995 | ||
996 | filename = strdup(dso->long_name); | ||
997 | if (!filename) | ||
998 | return -ENOMEM; | ||
999 | |||
995 | if (full_paths) | 1000 | if (full_paths) |
996 | d_filename = filename; | 1001 | d_filename = filename; |
997 | else | 1002 | else |
@@ -1042,6 +1047,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, | |||
1042 | } | 1047 | } |
1043 | } | 1048 | } |
1044 | 1049 | ||
1050 | free(filename); | ||
1051 | |||
1045 | return more; | 1052 | return more; |
1046 | } | 1053 | } |
1047 | 1054 | ||
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index b1817f15bb8..0ba65ad07cd 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -563,39 +563,6 @@ void hists__output_resort_threaded(struct hists *hists) | |||
563 | return __hists__output_resort(hists, true); | 563 | return __hists__output_resort(hists, true); |
564 | } | 564 | } |
565 | 565 | ||
566 | /* | ||
567 | * See hists__fprintf to match the column widths | ||
568 | */ | ||
569 | unsigned int hists__sort_list_width(struct hists *hists) | ||
570 | { | ||
571 | struct sort_entry *se; | ||
572 | int ret = 9; /* total % */ | ||
573 | |||
574 | if (symbol_conf.show_cpu_utilization) { | ||
575 | ret += 7; /* count_sys % */ | ||
576 | ret += 6; /* count_us % */ | ||
577 | if (perf_guest) { | ||
578 | ret += 13; /* count_guest_sys % */ | ||
579 | ret += 12; /* count_guest_us % */ | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if (symbol_conf.show_nr_samples) | ||
584 | ret += 11; | ||
585 | |||
586 | if (symbol_conf.show_total_period) | ||
587 | ret += 13; | ||
588 | |||
589 | list_for_each_entry(se, &hist_entry__sort_list, list) | ||
590 | if (!se->elide) | ||
591 | ret += 2 + hists__col_len(hists, se->se_width_idx); | ||
592 | |||
593 | if (verbose) /* Addr + origin */ | ||
594 | ret += 3 + BITS_PER_LONG / 4; | ||
595 | |||
596 | return ret; | ||
597 | } | ||
598 | |||
599 | static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, | 566 | static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, |
600 | enum hist_filter filter) | 567 | enum hist_filter filter) |
601 | { | 568 | { |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 2e650ffb7d2..4146f51124f 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -115,6 +115,43 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); | |||
115 | void hists__reset_col_len(struct hists *hists); | 115 | void hists__reset_col_len(struct hists *hists); |
116 | void hists__calc_col_len(struct hists *hists, struct hist_entry *he); | 116 | void hists__calc_col_len(struct hists *hists, struct hist_entry *he); |
117 | 117 | ||
118 | struct perf_hpp { | ||
119 | char *buf; | ||
120 | size_t size; | ||
121 | u64 total_period; | ||
122 | const char *sep; | ||
123 | long displacement; | ||
124 | void *ptr; | ||
125 | }; | ||
126 | |||
127 | struct perf_hpp_fmt { | ||
128 | bool cond; | ||
129 | int (*header)(struct perf_hpp *hpp); | ||
130 | int (*width)(struct perf_hpp *hpp); | ||
131 | int (*color)(struct perf_hpp *hpp, struct hist_entry *he); | ||
132 | int (*entry)(struct perf_hpp *hpp, struct hist_entry *he); | ||
133 | }; | ||
134 | |||
135 | extern struct perf_hpp_fmt perf_hpp__format[]; | ||
136 | |||
137 | enum { | ||
138 | PERF_HPP__OVERHEAD, | ||
139 | PERF_HPP__OVERHEAD_SYS, | ||
140 | PERF_HPP__OVERHEAD_US, | ||
141 | PERF_HPP__OVERHEAD_GUEST_SYS, | ||
142 | PERF_HPP__OVERHEAD_GUEST_US, | ||
143 | PERF_HPP__SAMPLES, | ||
144 | PERF_HPP__PERIOD, | ||
145 | PERF_HPP__DELTA, | ||
146 | PERF_HPP__DISPL, | ||
147 | |||
148 | PERF_HPP__MAX_INDEX | ||
149 | }; | ||
150 | |||
151 | void perf_hpp__init(bool need_pair, bool show_displacement); | ||
152 | int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, | ||
153 | bool color); | ||
154 | |||
118 | struct perf_evlist; | 155 | struct perf_evlist; |
119 | 156 | ||
120 | #ifdef NO_NEWT_SUPPORT | 157 | #ifdef NO_NEWT_SUPPORT |
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index b6842c1d02a..4af9a10cc2d 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h | |||
@@ -47,8 +47,12 @@ | |||
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #ifndef BUG_ON | 49 | #ifndef BUG_ON |
50 | #ifdef NDEBUG | ||
51 | #define BUG_ON(cond) do { if (cond) {} } while (0) | ||
52 | #else | ||
50 | #define BUG_ON(cond) assert(!(cond)) | 53 | #define BUG_ON(cond) assert(!(cond)) |
51 | #endif | 54 | #endif |
55 | #endif | ||
52 | 56 | ||
53 | /* | 57 | /* |
54 | * Both need more care to handle endianness | 58 | * Both need more care to handle endianness |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 0dda25d82d0..e8c72de0f70 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -2307,10 +2307,17 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) | |||
2307 | function = NULL; | 2307 | function = NULL; |
2308 | } | 2308 | } |
2309 | if (!pev->group) { | 2309 | if (!pev->group) { |
2310 | char *ptr1, *ptr2; | 2310 | char *ptr1, *ptr2, *exec_copy; |
2311 | 2311 | ||
2312 | pev->group = zalloc(sizeof(char *) * 64); | 2312 | pev->group = zalloc(sizeof(char *) * 64); |
2313 | ptr1 = strdup(basename(exec)); | 2313 | exec_copy = strdup(exec); |
2314 | if (!exec_copy) { | ||
2315 | ret = -ENOMEM; | ||
2316 | pr_warning("Failed to copy exec string.\n"); | ||
2317 | goto out; | ||
2318 | } | ||
2319 | |||
2320 | ptr1 = strdup(basename(exec_copy)); | ||
2314 | if (ptr1) { | 2321 | if (ptr1) { |
2315 | ptr2 = strpbrk(ptr1, "-._"); | 2322 | ptr2 = strpbrk(ptr1, "-._"); |
2316 | if (ptr2) | 2323 | if (ptr2) |
@@ -2319,6 +2326,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) | |||
2319 | ptr1); | 2326 | ptr1); |
2320 | free(ptr1); | 2327 | free(ptr1); |
2321 | } | 2328 | } |
2329 | free(exec_copy); | ||
2322 | } | 2330 | } |
2323 | free(pp->function); | 2331 | free(pp->function); |
2324 | pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); | 2332 | pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index d3b330cbc3e..41a15dac412 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -10,9 +10,7 @@ | |||
10 | #include <linux/rbtree.h> | 10 | #include <linux/rbtree.h> |
11 | #include <stdio.h> | 11 | #include <stdio.h> |
12 | #include <byteswap.h> | 12 | #include <byteswap.h> |
13 | #if defined(__BIONIC__) | ||
14 | #include <libgen.h> | 13 | #include <libgen.h> |
15 | #endif | ||
16 | 14 | ||
17 | #ifndef NO_LIBELF_SUPPORT | 15 | #ifndef NO_LIBELF_SUPPORT |
18 | #include <libelf.h> | 16 | #include <libelf.h> |