Commit 30e863bb authored by Andi Kleen's avatar Andi Kleen Committed by Arnaldo Carvalho de Melo

perf annotate: Compute IPC and basic block cycles

Compute the IPC and the basic block cycles for the annotate display.

IPC is computed by counting the instructions, and then dividing the
accounted cycles by that count.

The actual IPC computation can only be done at annotate time, because we
need to parse the objdump output first to know the number of
instructions in the basic block.

The cycles/IPC are also put into the perf function annotation so that
the display code can show them.

Again basic block overlaps are not handled, with the longest winning,
but there are some heuristics to hide the IPC when the longest is not
the most common.

v2: Compute IPC correctly.
Signed-off-by: default avatarAndi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/1437233094-12844-6-git-send-email-andi@firstfloor.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 57849998
...@@ -53,6 +53,7 @@ struct annotate_browser { ...@@ -53,6 +53,7 @@ struct annotate_browser {
int max_jump_sources; int max_jump_sources;
int nr_jumps; int nr_jumps;
bool searching_backwards; bool searching_backwards;
bool have_cycles;
u8 addr_width; u8 addr_width;
u8 jumps_width; u8 jumps_width;
u8 target_width; u8 target_width;
...@@ -390,7 +391,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, ...@@ -390,7 +391,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
max_percent = bpos->samples[i].percent; max_percent = bpos->samples[i].percent;
} }
if (max_percent < 0.01) { if (max_percent < 0.01 && pos->ipc == 0) {
RB_CLEAR_NODE(&bpos->rb_node); RB_CLEAR_NODE(&bpos->rb_node);
continue; continue;
} }
...@@ -869,6 +870,75 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, ...@@ -869,6 +870,75 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
return map_symbol__tui_annotate(&he->ms, evsel, hbt); return map_symbol__tui_annotate(&he->ms, evsel, hbt);
} }
static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end)
{
unsigned n_insn = 0;
u64 offset;
for (offset = start; offset <= end; offset++) {
if (browser->offsets[offset])
n_insn++;
}
return n_insn;
}
static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,
struct cyc_hist *ch)
{
unsigned n_insn;
u64 offset;
n_insn = count_insn(browser, start, end);
if (n_insn && ch->num && ch->cycles) {
float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
/* Hide data when there are too many overlaps. */
if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
return;
for (offset = start; offset <= end; offset++) {
struct disasm_line *dl = browser->offsets[offset];
if (dl)
dl->ipc = ipc;
}
}
}
/*
* This should probably be in util/annotate.c to share with the tty
* annotate, but right now we need the per byte offsets arrays,
* which are only here.
*/
static void annotate__compute_ipc(struct annotate_browser *browser, size_t size,
struct symbol *sym)
{
u64 offset;
struct annotation *notes = symbol__annotation(sym);
if (!notes->src || !notes->src->cycles_hist)
return;
pthread_mutex_lock(&notes->lock);
for (offset = 0; offset < size; ++offset) {
struct cyc_hist *ch;
ch = &notes->src->cycles_hist[offset];
if (ch && ch->cycles) {
struct disasm_line *dl;
if (ch->have_start)
count_and_fill(browser, ch->start, offset, ch);
dl = browser->offsets[offset];
if (dl && ch->num_aggr)
dl->cycles = ch->cycles_aggr / ch->num_aggr;
browser->have_cycles = true;
}
}
pthread_mutex_unlock(&notes->lock);
}
static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
size_t size) size_t size)
{ {
...@@ -991,6 +1061,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, ...@@ -991,6 +1061,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
} }
annotate_browser__mark_jump_targets(&browser, size); annotate_browser__mark_jump_targets(&browser, size);
annotate__compute_ipc(&browser, size, sym);
browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size); browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);
browser.max_addr_width = hex_width(sym->end); browser.max_addr_width = hex_width(sym->end);
......
...@@ -59,6 +59,8 @@ struct disasm_line { ...@@ -59,6 +59,8 @@ struct disasm_line {
char *name; char *name;
struct ins *ins; struct ins *ins;
int line_nr; int line_nr;
float ipc;
u64 cycles;
struct ins_operands ops; struct ins_operands ops;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment