aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/ui/browsers/annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/ui/browsers/annotate.c')
-rw-r--r--tools/perf/ui/browsers/annotate.c158
1 files changed, 98 insertions, 60 deletions
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 7dca1555c610..cc64d3f7fc36 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -8,15 +8,19 @@
8#include "../../util/hist.h" 8#include "../../util/hist.h"
9#include "../../util/sort.h" 9#include "../../util/sort.h"
10#include "../../util/symbol.h" 10#include "../../util/symbol.h"
11#include "../../util/evsel.h"
11#include <pthread.h> 12#include <pthread.h>
12#include <newt.h>
13 13
14struct browser_disasm_line { 14struct browser_disasm_line {
15 struct rb_node rb_node; 15 struct rb_node rb_node;
16 double percent;
17 u32 idx; 16 u32 idx;
18 int idx_asm; 17 int idx_asm;
19 int jump_sources; 18 int jump_sources;
19 /*
20 * actual length of this array is saved on the nr_events field
21 * of the struct annotate_browser
22 */
23 double percent[1];
20}; 24};
21 25
22static struct annotate_browser_opt { 26static struct annotate_browser_opt {
@@ -33,8 +37,9 @@ struct annotate_browser {
33 struct ui_browser b; 37 struct ui_browser b;
34 struct rb_root entries; 38 struct rb_root entries;
35 struct rb_node *curr_hot; 39 struct rb_node *curr_hot;
36 struct disasm_line *selection; 40 struct disasm_line *selection;
37 struct disasm_line **offsets; 41 struct disasm_line **offsets;
42 int nr_events;
38 u64 start; 43 u64 start;
39 int nr_asm_entries; 44 int nr_asm_entries;
40 int nr_entries; 45 int nr_entries;
@@ -94,14 +99,24 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
94 (!current_entry || (browser->use_navkeypressed && 99 (!current_entry || (browser->use_navkeypressed &&
95 !browser->navkeypressed))); 100 !browser->navkeypressed)));
96 int width = browser->width, printed; 101 int width = browser->width, printed;
102 int i, pcnt_width = 7 * ab->nr_events;
103 double percent_max = 0.0;
97 char bf[256]; 104 char bf[256];
98 105
99 if (dl->offset != -1 && bdl->percent != 0.0) { 106 for (i = 0; i < ab->nr_events; i++) {
100 ui_browser__set_percent_color(browser, bdl->percent, current_entry); 107 if (bdl->percent[i] > percent_max)
101 slsmg_printf("%6.2f ", bdl->percent); 108 percent_max = bdl->percent[i];
109 }
110
111 if (dl->offset != -1 && percent_max != 0.0) {
112 for (i = 0; i < ab->nr_events; i++) {
113 ui_browser__set_percent_color(browser, bdl->percent[i],
114 current_entry);
115 slsmg_printf("%6.2f ", bdl->percent[i]);
116 }
102 } else { 117 } else {
103 ui_browser__set_percent_color(browser, 0, current_entry); 118 ui_browser__set_percent_color(browser, 0, current_entry);
104 slsmg_write_nstring(" ", 7); 119 slsmg_write_nstring(" ", pcnt_width);
105 } 120 }
106 121
107 SLsmg_write_char(' '); 122 SLsmg_write_char(' ');
@@ -111,12 +126,12 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
111 width += 1; 126 width += 1;
112 127
113 if (!*dl->line) 128 if (!*dl->line)
114 slsmg_write_nstring(" ", width - 7); 129 slsmg_write_nstring(" ", width - pcnt_width);
115 else if (dl->offset == -1) { 130 else if (dl->offset == -1) {
116 printed = scnprintf(bf, sizeof(bf), "%*s ", 131 printed = scnprintf(bf, sizeof(bf), "%*s ",
117 ab->addr_width, " "); 132 ab->addr_width, " ");
118 slsmg_write_nstring(bf, printed); 133 slsmg_write_nstring(bf, printed);
119 slsmg_write_nstring(dl->line, width - printed - 6); 134 slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1);
120 } else { 135 } else {
121 u64 addr = dl->offset; 136 u64 addr = dl->offset;
122 int color = -1; 137 int color = -1;
@@ -175,7 +190,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
175 } 190 }
176 191
177 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 192 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
178 slsmg_write_nstring(bf, width - 10 - printed); 193 slsmg_write_nstring(bf, width - pcnt_width - 3 - printed);
179 } 194 }
180 195
181 if (current_entry) 196 if (current_entry)
@@ -200,6 +215,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
200 unsigned int from, to; 215 unsigned int from, to;
201 struct map_symbol *ms = ab->b.priv; 216 struct map_symbol *ms = ab->b.priv;
202 struct symbol *sym = ms->sym; 217 struct symbol *sym = ms->sym;
218 u8 pcnt_width = 7;
203 219
204 /* PLT symbols contain external offsets */ 220 /* PLT symbols contain external offsets */
205 if (strstr(sym->name, "@plt")) 221 if (strstr(sym->name, "@plt"))
@@ -223,57 +239,44 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
223 to = (u64)btarget->idx; 239 to = (u64)btarget->idx;
224 } 240 }
225 241
242 pcnt_width *= ab->nr_events;
243
226 ui_browser__set_color(browser, HE_COLORSET_CODE); 244 ui_browser__set_color(browser, HE_COLORSET_CODE);
227 __ui_browser__line_arrow(browser, 9 + ab->addr_width, from, to); 245 __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
246 from, to);
228} 247}
229 248
230static unsigned int annotate_browser__refresh(struct ui_browser *browser) 249static unsigned int annotate_browser__refresh(struct ui_browser *browser)
231{ 250{
251 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
232 int ret = ui_browser__list_head_refresh(browser); 252 int ret = ui_browser__list_head_refresh(browser);
253 int pcnt_width;
254
255 pcnt_width = 7 * ab->nr_events;
233 256
234 if (annotate_browser__opts.jump_arrows) 257 if (annotate_browser__opts.jump_arrows)
235 annotate_browser__draw_current_jump(browser); 258 annotate_browser__draw_current_jump(browser);
236 259
237 ui_browser__set_color(browser, HE_COLORSET_NORMAL); 260 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
238 __ui_browser__vline(browser, 7, 0, browser->height - 1); 261 __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
239 return ret; 262 return ret;
240} 263}
241 264
242static double disasm_line__calc_percent(struct disasm_line *dl, struct symbol *sym, int evidx) 265static int disasm__cmp(struct browser_disasm_line *a,
266 struct browser_disasm_line *b, int nr_pcnt)
243{ 267{
244 double percent = 0.0; 268 int i;
245
246 if (dl->offset != -1) {
247 int len = sym->end - sym->start;
248 unsigned int hits = 0;
249 struct annotation *notes = symbol__annotation(sym);
250 struct source_line *src_line = notes->src->lines;
251 struct sym_hist *h = annotation__histogram(notes, evidx);
252 s64 offset = dl->offset;
253 struct disasm_line *next;
254 269
255 next = disasm__get_next_ip_line(&notes->src->source, dl); 270 for (i = 0; i < nr_pcnt; i++) {
256 while (offset < (s64)len && 271 if (a->percent[i] == b->percent[i])
257 (next == NULL || offset < next->offset)) { 272 continue;
258 if (src_line) { 273 return a->percent[i] < b->percent[i];
259 percent += src_line[offset].percent;
260 } else
261 hits += h->addr[offset];
262
263 ++offset;
264 }
265 /*
266 * If the percentage wasn't already calculated in
267 * symbol__get_source_line, do it now:
268 */
269 if (src_line == NULL && h->sum)
270 percent = 100.0 * hits / h->sum;
271 } 274 }
272 275 return 0;
273 return percent;
274} 276}
275 277
276static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl) 278static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl,
279 int nr_events)
277{ 280{
278 struct rb_node **p = &root->rb_node; 281 struct rb_node **p = &root->rb_node;
279 struct rb_node *parent = NULL; 282 struct rb_node *parent = NULL;
@@ -282,7 +285,8 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_l
282 while (*p != NULL) { 285 while (*p != NULL) {
283 parent = *p; 286 parent = *p;
284 l = rb_entry(parent, struct browser_disasm_line, rb_node); 287 l = rb_entry(parent, struct browser_disasm_line, rb_node);
285 if (bdl->percent < l->percent) 288
289 if (disasm__cmp(bdl, l, nr_events))
286 p = &(*p)->rb_left; 290 p = &(*p)->rb_left;
287 else 291 else
288 p = &(*p)->rb_right; 292 p = &(*p)->rb_right;
@@ -331,12 +335,13 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,
331} 335}
332 336
333static void annotate_browser__calc_percent(struct annotate_browser *browser, 337static void annotate_browser__calc_percent(struct annotate_browser *browser,
334 int evidx) 338 struct perf_evsel *evsel)
335{ 339{
336 struct map_symbol *ms = browser->b.priv; 340 struct map_symbol *ms = browser->b.priv;
337 struct symbol *sym = ms->sym; 341 struct symbol *sym = ms->sym;
338 struct annotation *notes = symbol__annotation(sym); 342 struct annotation *notes = symbol__annotation(sym);
339 struct disasm_line *pos; 343 struct disasm_line *pos, *next;
344 s64 len = symbol__size(sym);
340 345
341 browser->entries = RB_ROOT; 346 browser->entries = RB_ROOT;
342 347
@@ -344,12 +349,34 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
344 349
345 list_for_each_entry(pos, &notes->src->source, node) { 350 list_for_each_entry(pos, &notes->src->source, node) {
346 struct browser_disasm_line *bpos = disasm_line__browser(pos); 351 struct browser_disasm_line *bpos = disasm_line__browser(pos);
347 bpos->percent = disasm_line__calc_percent(pos, sym, evidx); 352 const char *path = NULL;
348 if (bpos->percent < 0.01) { 353 double max_percent = 0.0;
354 int i;
355
356 if (pos->offset == -1) {
357 RB_CLEAR_NODE(&bpos->rb_node);
358 continue;
359 }
360
361 next = disasm__get_next_ip_line(&notes->src->source, pos);
362
363 for (i = 0; i < browser->nr_events; i++) {
364 bpos->percent[i] = disasm__calc_percent(notes,
365 evsel->idx + i,
366 pos->offset,
367 next ? next->offset : len,
368 &path);
369
370 if (max_percent < bpos->percent[i])
371 max_percent = bpos->percent[i];
372 }
373
374 if (max_percent < 0.01) {
349 RB_CLEAR_NODE(&bpos->rb_node); 375 RB_CLEAR_NODE(&bpos->rb_node);
350 continue; 376 continue;
351 } 377 }
352 disasm_rb_tree__insert(&browser->entries, bpos); 378 disasm_rb_tree__insert(&browser->entries, bpos,
379 browser->nr_events);
353 } 380 }
354 pthread_mutex_unlock(&notes->lock); 381 pthread_mutex_unlock(&notes->lock);
355 382
@@ -401,7 +428,8 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
401 browser->b.nr_entries = browser->nr_asm_entries; 428 browser->b.nr_entries = browser->nr_asm_entries;
402} 429}
403 430
404static bool annotate_browser__callq(struct annotate_browser *browser, int evidx, 431static bool annotate_browser__callq(struct annotate_browser *browser,
432 struct perf_evsel *evsel,
405 struct hist_browser_timer *hbt) 433 struct hist_browser_timer *hbt)
406{ 434{
407 struct map_symbol *ms = browser->b.priv; 435 struct map_symbol *ms = browser->b.priv;
@@ -432,7 +460,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, int evidx,
432 } 460 }
433 461
434 pthread_mutex_unlock(&notes->lock); 462 pthread_mutex_unlock(&notes->lock);
435 symbol__tui_annotate(target, ms->map, evidx, hbt); 463 symbol__tui_annotate(target, ms->map, evsel, hbt);
436 ui_browser__show_title(&browser->b, sym->name); 464 ui_browser__show_title(&browser->b, sym->name);
437 return true; 465 return true;
438} 466}
@@ -615,7 +643,8 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser
615 browser->addr_width += browser->jumps_width + 1; 643 browser->addr_width += browser->jumps_width + 1;
616} 644}
617 645
618static int annotate_browser__run(struct annotate_browser *browser, int evidx, 646static int annotate_browser__run(struct annotate_browser *browser,
647 struct perf_evsel *evsel,
619 struct hist_browser_timer *hbt) 648 struct hist_browser_timer *hbt)
620{ 649{
621 struct rb_node *nd = NULL; 650 struct rb_node *nd = NULL;
@@ -628,7 +657,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
628 if (ui_browser__show(&browser->b, sym->name, help) < 0) 657 if (ui_browser__show(&browser->b, sym->name, help) < 0)
629 return -1; 658 return -1;
630 659
631 annotate_browser__calc_percent(browser, evidx); 660 annotate_browser__calc_percent(browser, evsel);
632 661
633 if (browser->curr_hot) { 662 if (browser->curr_hot) {
634 annotate_browser__set_rb_top(browser, browser->curr_hot); 663 annotate_browser__set_rb_top(browser, browser->curr_hot);
@@ -641,7 +670,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
641 key = ui_browser__run(&browser->b, delay_secs); 670 key = ui_browser__run(&browser->b, delay_secs);
642 671
643 if (delay_secs != 0) { 672 if (delay_secs != 0) {
644 annotate_browser__calc_percent(browser, evidx); 673 annotate_browser__calc_percent(browser, evsel);
645 /* 674 /*
646 * Current line focus got out of the list of most active 675 * Current line focus got out of the list of most active
647 * lines, NULL it so that if TAB|UNTAB is pressed, we 676 * lines, NULL it so that if TAB|UNTAB is pressed, we
@@ -657,7 +686,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
657 hbt->timer(hbt->arg); 686 hbt->timer(hbt->arg);
658 687
659 if (delay_secs != 0) 688 if (delay_secs != 0)
660 symbol__annotate_decay_histogram(sym, evidx); 689 symbol__annotate_decay_histogram(sym, evsel->idx);
661 continue; 690 continue;
662 case K_TAB: 691 case K_TAB:
663 if (nd != NULL) { 692 if (nd != NULL) {
@@ -754,7 +783,7 @@ show_help:
754 goto show_sup_ins; 783 goto show_sup_ins;
755 goto out; 784 goto out;
756 } else if (!(annotate_browser__jump(browser) || 785 } else if (!(annotate_browser__jump(browser) ||
757 annotate_browser__callq(browser, evidx, hbt))) { 786 annotate_browser__callq(browser, evsel, hbt))) {
758show_sup_ins: 787show_sup_ins:
759 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 788 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");
760 } 789 }
@@ -776,10 +805,10 @@ out:
776 return key; 805 return key;
777} 806}
778 807
779int hist_entry__tui_annotate(struct hist_entry *he, int evidx, 808int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
780 struct hist_browser_timer *hbt) 809 struct hist_browser_timer *hbt)
781{ 810{
782 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, hbt); 811 return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt);
783} 812}
784 813
785static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 814static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
@@ -826,7 +855,8 @@ static inline int width_jumps(int n)
826 return 1; 855 return 1;
827} 856}
828 857
829int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 858int symbol__tui_annotate(struct symbol *sym, struct map *map,
859 struct perf_evsel *evsel,
830 struct hist_browser_timer *hbt) 860 struct hist_browser_timer *hbt)
831{ 861{
832 struct disasm_line *pos, *n; 862 struct disasm_line *pos, *n;
@@ -847,6 +877,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
847 }, 877 },
848 }; 878 };
849 int ret = -1; 879 int ret = -1;
880 int nr_pcnt = 1;
881 size_t sizeof_bdl = sizeof(struct browser_disasm_line);
850 882
851 if (sym == NULL) 883 if (sym == NULL)
852 return -1; 884 return -1;
@@ -862,7 +894,12 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
862 return -1; 894 return -1;
863 } 895 }
864 896
865 if (symbol__annotate(sym, map, sizeof(struct browser_disasm_line)) < 0) { 897 if (perf_evsel__is_group_event(evsel)) {
898 nr_pcnt = evsel->nr_members;
899 sizeof_bdl += sizeof(double) * (nr_pcnt - 1);
900 }
901
902 if (symbol__annotate(sym, map, sizeof_bdl) < 0) {
866 ui__error("%s", ui_helpline__last_msg); 903 ui__error("%s", ui_helpline__last_msg);
867 goto out_free_offsets; 904 goto out_free_offsets;
868 } 905 }
@@ -900,6 +937,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
900 browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); 937 browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);
901 browser.max_addr_width = hex_width(sym->end); 938 browser.max_addr_width = hex_width(sym->end);
902 browser.jumps_width = width_jumps(browser.max_jump_sources); 939 browser.jumps_width = width_jumps(browser.max_jump_sources);
940 browser.nr_events = nr_pcnt;
903 browser.b.nr_entries = browser.nr_entries; 941 browser.b.nr_entries = browser.nr_entries;
904 browser.b.entries = &notes->src->source, 942 browser.b.entries = &notes->src->source,
905 browser.b.width += 18; /* Percentage */ 943 browser.b.width += 18; /* Percentage */
@@ -909,7 +947,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
909 947
910 annotate_browser__update_addr_width(&browser); 948 annotate_browser__update_addr_width(&browser);
911 949
912 ret = annotate_browser__run(&browser, evidx, hbt); 950 ret = annotate_browser__run(&browser, evsel, hbt);
913 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 951 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
914 list_del(&pos->node); 952 list_del(&pos->node);
915 disasm_line__free(pos); 953 disasm_line__free(pos);