summaryrefslogtreecommitdiffstats
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 @@
#include "../../util/hist.h"
#include "../../util/sort.h"
#include "../../util/symbol.h"
+#include "../../util/evsel.h"
#include <pthread.h>
-#include <newt.h>
struct browser_disasm_line {
struct rb_node rb_node;
- double percent;
u32 idx;
int idx_asm;
int jump_sources;
+ /*
+ * actual length of this array is saved on the nr_events field
+ * of the struct annotate_browser
+ */
+ double percent[1];
};
static struct annotate_browser_opt {
@@ -33,8 +37,9 @@ struct annotate_browser {
struct ui_browser b;
struct rb_root entries;
struct rb_node *curr_hot;
- struct disasm_line *selection;
+ struct disasm_line *selection;
struct disasm_line **offsets;
+ int nr_events;
u64 start;
int nr_asm_entries;
int nr_entries;
@@ -94,14 +99,24 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
(!current_entry || (browser->use_navkeypressed &&
!browser->navkeypressed)));
int width = browser->width, printed;
+ int i, pcnt_width = 7 * ab->nr_events;
+ double percent_max = 0.0;
char bf[256];
- if (dl->offset != -1 && bdl->percent != 0.0) {
- ui_browser__set_percent_color(browser, bdl->percent, current_entry);
- slsmg_printf("%6.2f ", bdl->percent);
+ for (i = 0; i < ab->nr_events; i++) {
+ if (bdl->percent[i] > percent_max)
+ percent_max = bdl->percent[i];
+ }
+
+ if (dl->offset != -1 && percent_max != 0.0) {
+ for (i = 0; i < ab->nr_events; i++) {
+ ui_browser__set_percent_color(browser, bdl->percent[i],
+ current_entry);
+ slsmg_printf("%6.2f ", bdl->percent[i]);
+ }
} else {
ui_browser__set_percent_color(browser, 0, current_entry);
- slsmg_write_nstring(" ", 7);
+ slsmg_write_nstring(" ", pcnt_width);
}
SLsmg_write_char(' ');
@@ -111,12 +126,12 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
width += 1;
if (!*dl->line)
- slsmg_write_nstring(" ", width - 7);
+ slsmg_write_nstring(" ", width - pcnt_width);
else if (dl->offset == -1) {
printed = scnprintf(bf, sizeof(bf), "%*s ",
ab->addr_width, " ");
slsmg_write_nstring(bf, printed);
- slsmg_write_nstring(dl->line, width - printed - 6);
+ slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1);
} else {
u64 addr = dl->offset;
int color = -1;
@@ -175,7 +190,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
}
disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
- slsmg_write_nstring(bf, width - 10 - printed);
+ slsmg_write_nstring(bf, width - pcnt_width - 3 - printed);
}
if (current_entry)
@@ -200,6 +215,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
unsigned int from, to;
struct map_symbol *ms = ab->b.priv;
struct symbol *sym = ms->sym;
+ u8 pcnt_width = 7;
/* PLT symbols contain external offsets */
if (strstr(sym->name, "@plt"))
@@ -223,57 +239,44 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
to = (u64)btarget->idx;
}
+ pcnt_width *= ab->nr_events;
+
ui_browser__set_color(browser, HE_COLORSET_CODE);
- __ui_browser__line_arrow(browser, 9 + ab->addr_width, from, to);
+ __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
+ from, to);
}
static unsigned int annotate_browser__refresh(struct ui_browser *browser)
{
+ struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
int ret = ui_browser__list_head_refresh(browser);
+ int pcnt_width;
+
+ pcnt_width = 7 * ab->nr_events;
if (annotate_browser__opts.jump_arrows)
annotate_browser__draw_current_jump(browser);
ui_browser__set_color(browser, HE_COLORSET_NORMAL);
- __ui_browser__vline(browser, 7, 0, browser->height - 1);
+ __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1);
return ret;
}
-static double disasm_line__calc_percent(struct disasm_line *dl, struct symbol *sym, int evidx)
+static int disasm__cmp(struct browser_disasm_line *a,
+ struct browser_disasm_line *b, int nr_pcnt)
{
- double percent = 0.0;
-
- if (dl->offset != -1) {
- int len = sym->end - sym->start;
- unsigned int hits = 0;
- struct annotation *notes = symbol__annotation(sym);
- struct source_line *src_line = notes->src->lines;
- struct sym_hist *h = annotation__histogram(notes, evidx);
- s64 offset = dl->offset;
- struct disasm_line *next;
+ int i;
- next = disasm__get_next_ip_line(&notes->src->source, dl);
- while (offset < (s64)len &&
- (next == NULL || offset < next->offset)) {
- if (src_line) {
- percent += src_line[offset].percent;
- } else
- hits += h->addr[offset];
-
- ++offset;
- }
- /*
- * If the percentage wasn't already calculated in
- * symbol__get_source_line, do it now:
- */
- if (src_line == NULL && h->sum)
- percent = 100.0 * hits / h->sum;
+ for (i = 0; i < nr_pcnt; i++) {
+ if (a->percent[i] == b->percent[i])
+ continue;
+ return a->percent[i] < b->percent[i];
}
-
- return percent;
+ return 0;
}
-static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl)
+static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_line *bdl,
+ int nr_events)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
@@ -282,7 +285,8 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct browser_disasm_l
while (*p != NULL) {
parent = *p;
l = rb_entry(parent, struct browser_disasm_line, rb_node);
- if (bdl->percent < l->percent)
+
+ if (disasm__cmp(bdl, l, nr_events))
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
@@ -331,12 +335,13 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,
}
static void annotate_browser__calc_percent(struct annotate_browser *browser,
- int evidx)
+ struct perf_evsel *evsel)
{
struct map_symbol *ms = browser->b.priv;
struct symbol *sym = ms->sym;
struct annotation *notes = symbol__annotation(sym);
- struct disasm_line *pos;
+ struct disasm_line *pos, *next;
+ s64 len = symbol__size(sym);
browser->entries = RB_ROOT;
@@ -344,12 +349,34 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
list_for_each_entry(pos, &notes->src->source, node) {
struct browser_disasm_line *bpos = disasm_line__browser(pos);
- bpos->percent = disasm_line__calc_percent(pos, sym, evidx);
- if (bpos->percent < 0.01) {
+ const char *path = NULL;
+ double max_percent = 0.0;
+ int i;
+
+ if (pos->offset == -1) {
+ RB_CLEAR_NODE(&bpos->rb_node);
+ continue;
+ }
+
+ next = disasm__get_next_ip_line(&notes->src->source, pos);
+
+ for (i = 0; i < browser->nr_events; i++) {
+ bpos->percent[i] = disasm__calc_percent(notes,
+ evsel->idx + i,
+ pos->offset,
+ next ? next->offset : len,
+ &path);
+
+ if (max_percent < bpos->percent[i])
+ max_percent = bpos->percent[i];
+ }
+
+ if (max_percent < 0.01) {
RB_CLEAR_NODE(&bpos->rb_node);
continue;
}
- disasm_rb_tree__insert(&browser->entries, bpos);
+ disasm_rb_tree__insert(&browser->entries, bpos,
+ browser->nr_events);
}
pthread_mutex_unlock(&notes->lock);
@@ -401,7 +428,8 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
browser->b.nr_entries = browser->nr_asm_entries;
}
-static bool annotate_browser__callq(struct annotate_browser *browser, int evidx,
+static bool annotate_browser__callq(struct annotate_browser *browser,
+ struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
{
struct map_symbol *ms = browser->b.priv;
@@ -432,7 +460,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, int evidx,
}
pthread_mutex_unlock(&notes->lock);
- symbol__tui_annotate(target, ms->map, evidx, hbt);
+ symbol__tui_annotate(target, ms->map, evsel, hbt);
ui_browser__show_title(&browser->b, sym->name);
return true;
}
@@ -615,7 +643,8 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser
browser->addr_width += browser->jumps_width + 1;
}
-static int annotate_browser__run(struct annotate_browser *browser, int evidx,
+static int annotate_browser__run(struct annotate_browser *browser,
+ struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
{
struct rb_node *nd = NULL;
@@ -628,7 +657,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
if (ui_browser__show(&browser->b, sym->name, help) < 0)
return -1;
- annotate_browser__calc_percent(browser, evidx);
+ annotate_browser__calc_percent(browser, evsel);
if (browser->curr_hot) {
annotate_browser__set_rb_top(browser, browser->curr_hot);
@@ -641,7 +670,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
key = ui_browser__run(&browser->b, delay_secs);
if (delay_secs != 0) {
- annotate_browser__calc_percent(browser, evidx);
+ annotate_browser__calc_percent(browser, evsel);
/*
* Current line focus got out of the list of most active
* 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,
hbt->timer(hbt->arg);
if (delay_secs != 0)
- symbol__annotate_decay_histogram(sym, evidx);
+ symbol__annotate_decay_histogram(sym, evsel->idx);
continue;
case K_TAB:
if (nd != NULL) {
@@ -754,7 +783,7 @@ show_help:
goto show_sup_ins;
goto out;
} else if (!(annotate_browser__jump(browser) ||
- annotate_browser__callq(browser, evidx, hbt))) {
+ annotate_browser__callq(browser, evsel, hbt))) {
show_sup_ins:
ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");
}
@@ -776,10 +805,10 @@ out:
return key;
}
-int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
+int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
{
- return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, hbt);
+ return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt);
}
static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
@@ -826,7 +855,8 @@ static inline int width_jumps(int n)
return 1;
}
-int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
+int symbol__tui_annotate(struct symbol *sym, struct map *map,
+ struct perf_evsel *evsel,
struct hist_browser_timer *hbt)
{
struct disasm_line *pos, *n;
@@ -847,6 +877,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
},
};
int ret = -1;
+ int nr_pcnt = 1;
+ size_t sizeof_bdl = sizeof(struct browser_disasm_line);
if (sym == NULL)
return -1;
@@ -862,7 +894,12 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
return -1;
}
- if (symbol__annotate(sym, map, sizeof(struct browser_disasm_line)) < 0) {
+ if (perf_evsel__is_group_event(evsel)) {
+ nr_pcnt = evsel->nr_members;
+ sizeof_bdl += sizeof(double) * (nr_pcnt - 1);
+ }
+
+ if (symbol__annotate(sym, map, sizeof_bdl) < 0) {
ui__error("%s", ui_helpline__last_msg);
goto out_free_offsets;
}
@@ -900,6 +937,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);
browser.max_addr_width = hex_width(sym->end);
browser.jumps_width = width_jumps(browser.max_jump_sources);
+ browser.nr_events = nr_pcnt;
browser.b.nr_entries = browser.nr_entries;
browser.b.entries = &notes->src->source,
browser.b.width += 18; /* Percentage */
@@ -909,7 +947,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
annotate_browser__update_addr_width(&browser);
- ret = annotate_browser__run(&browser, evidx, hbt);
+ ret = annotate_browser__run(&browser, evsel, hbt);
list_for_each_entry_safe(pos, n, &notes->src->source, node) {
list_del(&pos->node);
disasm_line__free(pos);