diff options
Diffstat (limited to 'tools/perf/util/ui/browsers/annotate.c')
-rw-r--r-- | tools/perf/util/ui/browsers/annotate.c | 153 |
1 files changed, 115 insertions, 38 deletions
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 5b01df633f9..763592b09d7 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c | |||
@@ -14,6 +14,23 @@ static void ui__error_window(const char *fmt, ...) | |||
14 | va_end(ap); | 14 | va_end(ap); |
15 | } | 15 | } |
16 | 16 | ||
17 | struct annotate_browser { | ||
18 | struct ui_browser b; | ||
19 | struct rb_root entries; | ||
20 | }; | ||
21 | |||
22 | struct objdump_line_rb_node { | ||
23 | struct rb_node rb_node; | ||
24 | double percent; | ||
25 | u32 idx; | ||
26 | }; | ||
27 | |||
28 | static inline | ||
29 | struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self) | ||
30 | { | ||
31 | return (struct objdump_line_rb_node *)(self + 1); | ||
32 | } | ||
33 | |||
17 | static void annotate_browser__write(struct ui_browser *self, void *entry, int row) | 34 | static void annotate_browser__write(struct ui_browser *self, void *entry, int row) |
18 | { | 35 | { |
19 | struct objdump_line *ol = rb_entry(entry, struct objdump_line, node); | 36 | struct objdump_line *ol = rb_entry(entry, struct objdump_line, node); |
@@ -21,17 +38,41 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro | |||
21 | int width = self->width; | 38 | int width = self->width; |
22 | 39 | ||
23 | if (ol->offset != -1) { | 40 | if (ol->offset != -1) { |
24 | struct hist_entry *he = self->priv; | 41 | struct objdump_line_rb_node *olrb = objdump_line__rb(ol); |
25 | struct symbol *sym = he->ms.sym; | 42 | int color = ui_browser__percent_color(olrb->percent, current_entry); |
26 | int len = he->ms.sym->end - he->ms.sym->start; | 43 | SLsmg_set_color(color); |
44 | slsmg_printf(" %7.2f ", olrb->percent); | ||
45 | if (!current_entry) | ||
46 | SLsmg_set_color(HE_COLORSET_CODE); | ||
47 | } else { | ||
48 | int color = ui_browser__percent_color(0, current_entry); | ||
49 | SLsmg_set_color(color); | ||
50 | slsmg_write_nstring(" ", 9); | ||
51 | } | ||
52 | |||
53 | SLsmg_write_char(':'); | ||
54 | slsmg_write_nstring(" ", 8); | ||
55 | if (!*ol->line) | ||
56 | slsmg_write_nstring(" ", width - 18); | ||
57 | else | ||
58 | slsmg_write_nstring(ol->line, width - 18); | ||
59 | } | ||
60 | |||
61 | static double objdump_line__calc_percent(struct objdump_line *self, | ||
62 | struct list_head *head, | ||
63 | struct symbol *sym) | ||
64 | { | ||
65 | double percent = 0.0; | ||
66 | |||
67 | if (self->offset != -1) { | ||
68 | int len = sym->end - sym->start; | ||
27 | unsigned int hits = 0; | 69 | unsigned int hits = 0; |
28 | double percent = 0.0; | ||
29 | int color; | ||
30 | struct sym_priv *priv = symbol__priv(sym); | 70 | struct sym_priv *priv = symbol__priv(sym); |
31 | struct sym_ext *sym_ext = priv->ext; | 71 | struct sym_ext *sym_ext = priv->ext; |
32 | struct sym_hist *h = priv->hist; | 72 | struct sym_hist *h = priv->hist; |
33 | s64 offset = ol->offset; | 73 | s64 offset = self->offset; |
34 | struct objdump_line *next = objdump__get_next_ip_line(self->entries, ol); | 74 | struct objdump_line *next = objdump__get_next_ip_line(head, self); |
75 | |||
35 | 76 | ||
36 | while (offset < (s64)len && | 77 | while (offset < (s64)len && |
37 | (next == NULL || offset < next->offset)) { | 78 | (next == NULL || offset < next->offset)) { |
@@ -45,37 +86,45 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro | |||
45 | 86 | ||
46 | if (sym_ext == NULL && h->sum) | 87 | if (sym_ext == NULL && h->sum) |
47 | percent = 100.0 * hits / h->sum; | 88 | percent = 100.0 * hits / h->sum; |
48 | |||
49 | color = ui_browser__percent_color(percent, current_entry); | ||
50 | SLsmg_set_color(color); | ||
51 | slsmg_printf(" %7.2f ", percent); | ||
52 | if (!current_entry) | ||
53 | SLsmg_set_color(HE_COLORSET_CODE); | ||
54 | } else { | ||
55 | int color = ui_browser__percent_color(0, current_entry); | ||
56 | SLsmg_set_color(color); | ||
57 | slsmg_write_nstring(" ", 9); | ||
58 | } | 89 | } |
59 | 90 | ||
60 | SLsmg_write_char(':'); | 91 | return percent; |
61 | slsmg_write_nstring(" ", 8); | 92 | } |
62 | if (!*ol->line) | 93 | |
63 | slsmg_write_nstring(" ", width - 18); | 94 | static void objdump__insert_line(struct rb_root *self, |
64 | else | 95 | struct objdump_line_rb_node *line) |
65 | slsmg_write_nstring(ol->line, width - 18); | 96 | { |
97 | struct rb_node **p = &self->rb_node; | ||
98 | struct rb_node *parent = NULL; | ||
99 | struct objdump_line_rb_node *l; | ||
100 | |||
101 | while (*p != NULL) { | ||
102 | parent = *p; | ||
103 | l = rb_entry(parent, struct objdump_line_rb_node, rb_node); | ||
104 | if (line->percent < l->percent) | ||
105 | p = &(*p)->rb_left; | ||
106 | else | ||
107 | p = &(*p)->rb_right; | ||
108 | } | ||
109 | rb_link_node(&line->rb_node, parent, p); | ||
110 | rb_insert_color(&line->rb_node, self); | ||
66 | } | 111 | } |
67 | 112 | ||
68 | int hist_entry__tui_annotate(struct hist_entry *self) | 113 | int hist_entry__tui_annotate(struct hist_entry *self) |
69 | { | 114 | { |
70 | struct newtExitStruct es; | 115 | struct newtExitStruct es; |
71 | struct objdump_line *pos, *n; | 116 | struct objdump_line *pos, *n; |
117 | struct objdump_line_rb_node *rbpos; | ||
118 | struct rb_node *nd; | ||
72 | LIST_HEAD(head); | 119 | LIST_HEAD(head); |
73 | struct ui_browser browser = { | 120 | struct annotate_browser browser = { |
74 | .entries = &head, | 121 | .b = { |
75 | .refresh = ui_browser__list_head_refresh, | 122 | .entries = &head, |
76 | .seek = ui_browser__list_head_seek, | 123 | .refresh = ui_browser__list_head_refresh, |
77 | .write = annotate_browser__write, | 124 | .seek = ui_browser__list_head_seek, |
78 | .priv = self, | 125 | .write = annotate_browser__write, |
126 | .priv = self, | ||
127 | }, | ||
79 | }; | 128 | }; |
80 | int ret; | 129 | int ret; |
81 | 130 | ||
@@ -85,7 +134,7 @@ int hist_entry__tui_annotate(struct hist_entry *self) | |||
85 | if (self->ms.map->dso->annotate_warned) | 134 | if (self->ms.map->dso->annotate_warned) |
86 | return -1; | 135 | return -1; |
87 | 136 | ||
88 | if (hist_entry__annotate(self, &head) < 0) { | 137 | if (hist_entry__annotate(self, &head, sizeof(*rbpos)) < 0) { |
89 | ui__error_window(ui_helpline__last_msg); | 138 | ui__error_window(ui_helpline__last_msg); |
90 | return -1; | 139 | return -1; |
91 | } | 140 | } |
@@ -94,16 +143,44 @@ int hist_entry__tui_annotate(struct hist_entry *self) | |||
94 | 143 | ||
95 | list_for_each_entry(pos, &head, node) { | 144 | list_for_each_entry(pos, &head, node) { |
96 | size_t line_len = strlen(pos->line); | 145 | size_t line_len = strlen(pos->line); |
97 | if (browser.width < line_len) | 146 | if (browser.b.width < line_len) |
98 | browser.width = line_len; | 147 | browser.b.width = line_len; |
99 | ++browser.nr_entries; | 148 | rbpos = objdump_line__rb(pos); |
149 | rbpos->idx = browser.b.nr_entries++; | ||
150 | rbpos->percent = objdump_line__calc_percent(pos, &head, self->ms.sym); | ||
151 | if (rbpos->percent < 0.01) | ||
152 | continue; | ||
153 | objdump__insert_line(&browser.entries, rbpos); | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * Position the browser at the hottest line. | ||
158 | */ | ||
159 | nd = rb_last(&browser.entries); | ||
160 | if (nd != NULL) { | ||
161 | unsigned back; | ||
162 | |||
163 | ui_browser__refresh_dimensions(&browser.b); | ||
164 | back = browser.b.height / 2; | ||
165 | rbpos = rb_entry(nd, struct objdump_line_rb_node, rb_node); | ||
166 | pos = ((struct objdump_line *)rbpos) - 1; | ||
167 | browser.b.top_idx = browser.b.index = rbpos->idx; | ||
168 | |||
169 | while (browser.b.top_idx != 0 && back != 0) { | ||
170 | pos = list_entry(pos->node.prev, struct objdump_line, node); | ||
171 | |||
172 | --browser.b.top_idx; | ||
173 | --back; | ||
174 | } | ||
175 | |||
176 | browser.b.top = pos; | ||
100 | } | 177 | } |
101 | 178 | ||
102 | browser.width += 18; /* Percentage */ | 179 | browser.b.width += 18; /* Percentage */ |
103 | ui_browser__show(&browser, self->ms.sym->name); | 180 | ui_browser__show(&browser.b, self->ms.sym->name); |
104 | newtFormAddHotKey(browser.form, ' '); | 181 | newtFormAddHotKey(browser.b.form, ' '); |
105 | ret = ui_browser__run(&browser, &es); | 182 | ret = ui_browser__run(&browser.b, &es); |
106 | newtFormDestroy(browser.form); | 183 | newtFormDestroy(browser.b.form); |
107 | newtPopWindow(); | 184 | newtPopWindow(); |
108 | list_for_each_entry_safe(pos, n, &head, node) { | 185 | list_for_each_entry_safe(pos, n, &head, node) { |
109 | list_del(&pos->node); | 186 | list_del(&pos->node); |