perf annotate: Display the branch counter histogram
Display the branch counter histogram in the annotation view. Press 'B' to display the branch counter's abbreviation list as well. Samples: 1M of events 'anon group { branch-instructions:ppp, branch-misses }', 4000 Hz, Event count (approx.): f3 /home/sdp/test/tchain_edit [Percent: local period] Percent │ IPC Cycle Branch Counter (Average IPC: 1.39, IPC Coverage: 29.4%) │ 0000000000401755 <f3>: 0.00 0.00 │ endbr64 │ push %rbp │ mov %rsp,%rbp │ movl $0x0,-0x4(%rbp) 0.00 0.00 │1.33 3 |A |- | ↓ jmp 25 11.03 11.03 │ 11: mov -0x4(%rbp),%eax │ and $0x1,%eax │ test %eax,%eax 17.13 17.13 │2.41 1 |A |- | ↓ je 21 │ addl $0x1,-0x4(%rbp) 21.84 21.84 │2.22 2 |AA |- | ↓ jmp 25 17.13 17.13 │ 21: addl $0x1,-0x4(%rbp) 21.84 21.84 │ 25: cmpl $0x270f,-0x4(%rbp) 11.03 11.03 │0.61 3 |A |- | ↑ jle 11 │ nop │ pop %rbp 0.00 0.00 │0.24 20 |AA |B | ← ret Originally-by: Tinghao Zhang <tinghao.zhang@intel.com> Reviewed-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: https://lore.kernel.org/r/20240813160208.2493643-8-kan.liang@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
20d6f55528
commit
e6952dcec8
@ -927,11 +927,15 @@ int cmd_annotate(int argc, const char **argv)
|
||||
sort_order = "dso,symbol";
|
||||
|
||||
/*
|
||||
* Set SORT_MODE__BRANCH so that annotate display IPC/Cycle
|
||||
* if branch info is in perf data in TUI mode.
|
||||
* Set SORT_MODE__BRANCH so that annotate displays IPC/Cycle and
|
||||
* branch counters, if the corresponding branch info is available
|
||||
* in the perf data in the TUI mode.
|
||||
*/
|
||||
if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack)
|
||||
if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) {
|
||||
sort__mode = SORT_MODE__BRANCH;
|
||||
if (annotate.session->evlist->nr_br_cntr > 0)
|
||||
annotate_opts.show_br_cntr = true;
|
||||
}
|
||||
|
||||
if (setup_sorting(NULL) < 0)
|
||||
usage_with_options(annotate_usage, options);
|
||||
|
@ -156,6 +156,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
|
||||
struct symbol *sym = ms->sym;
|
||||
struct annotation *notes = symbol__annotation(sym);
|
||||
u8 pcnt_width = annotation__pcnt_width(notes);
|
||||
u8 cntr_width = annotation__br_cntr_width();
|
||||
int width;
|
||||
int diff = 0;
|
||||
|
||||
@ -205,13 +206,13 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
|
||||
|
||||
ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
|
||||
__ui_browser__line_arrow(browser,
|
||||
pcnt_width + 2 + notes->src->widths.addr + width,
|
||||
pcnt_width + 2 + notes->src->widths.addr + width + cntr_width,
|
||||
from, to);
|
||||
|
||||
diff = is_fused(ab, cursor);
|
||||
if (diff > 0) {
|
||||
ui_browser__mark_fused(browser,
|
||||
pcnt_width + 3 + notes->src->widths.addr + width,
|
||||
pcnt_width + 3 + notes->src->widths.addr + width + cntr_width,
|
||||
from - diff, diff, to > from);
|
||||
}
|
||||
}
|
||||
@ -714,6 +715,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
|
||||
struct annotation *notes = symbol__annotation(ms->sym);
|
||||
const char *help = "Press 'h' for help on key bindings";
|
||||
int delay_secs = hbt ? hbt->refresh : 0;
|
||||
char *br_cntr_text = NULL;
|
||||
char title[256];
|
||||
int key;
|
||||
|
||||
@ -730,6 +732,8 @@ static int annotate_browser__run(struct annotate_browser *browser,
|
||||
|
||||
nd = browser->curr_hot;
|
||||
|
||||
annotation_br_cntr_abbr_list(&br_cntr_text, evsel, false);
|
||||
|
||||
while (1) {
|
||||
key = ui_browser__run(&browser->b, delay_secs);
|
||||
|
||||
@ -796,6 +800,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
|
||||
"r Run available scripts\n"
|
||||
"p Toggle percent type [local/global]\n"
|
||||
"b Toggle percent base [period/hits]\n"
|
||||
"B Branch counter abbr list (Optional)\n"
|
||||
"? Search string backwards\n"
|
||||
"f Toggle showing offsets to full address\n");
|
||||
continue;
|
||||
@ -904,6 +909,14 @@ show_sup_ins:
|
||||
hists__scnprintf_title(hists, title, sizeof(title));
|
||||
annotate_browser__show(&browser->b, title, help);
|
||||
continue;
|
||||
case 'B':
|
||||
if (br_cntr_text)
|
||||
ui_browser__help_window(&browser->b, br_cntr_text);
|
||||
else {
|
||||
ui_browser__help_window(&browser->b,
|
||||
"\n The branch counter is not available.\n");
|
||||
}
|
||||
continue;
|
||||
case 'f':
|
||||
annotation__toggle_full_addr(notes, ms);
|
||||
continue;
|
||||
@ -923,6 +936,7 @@ show_sup_ins:
|
||||
}
|
||||
out:
|
||||
ui_browser__hide(&browser->b);
|
||||
free(br_cntr_text);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -3705,7 +3705,8 @@ int block_hists_tui_browse(struct block_hist *bh, struct evsel *evsel,
|
||||
|
||||
memset(&action, 0, sizeof(action));
|
||||
|
||||
annotation_br_cntr_abbr_list(&br_cntr_text, evsel, false);
|
||||
if (!annotation_br_cntr_abbr_list(&br_cntr_text, evsel, false))
|
||||
annotate_opts.show_br_cntr = true;
|
||||
|
||||
while (1) {
|
||||
key = hist_browser__run(browser, "? - help", true, 0);
|
||||
|
@ -501,8 +501,10 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64
|
||||
}
|
||||
}
|
||||
|
||||
static int annotation__compute_ipc(struct annotation *notes, size_t size)
|
||||
static int annotation__compute_ipc(struct annotation *notes, size_t size,
|
||||
struct evsel *evsel)
|
||||
{
|
||||
unsigned int br_cntr_nr = evsel->evlist->nr_br_cntr;
|
||||
int err = 0;
|
||||
s64 offset;
|
||||
|
||||
@ -537,6 +539,20 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size)
|
||||
al->cycles->max = ch->cycles_max;
|
||||
al->cycles->min = ch->cycles_min;
|
||||
}
|
||||
if (al && notes->branch->br_cntr) {
|
||||
if (!al->br_cntr) {
|
||||
al->br_cntr = calloc(br_cntr_nr, sizeof(u64));
|
||||
if (!al->br_cntr) {
|
||||
err = ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
al->num_aggr = ch->num_aggr;
|
||||
al->br_cntr_nr = br_cntr_nr;
|
||||
al->evsel = evsel;
|
||||
memcpy(al->br_cntr, ¬es->branch->br_cntr[offset * br_cntr_nr],
|
||||
br_cntr_nr * sizeof(u64));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -548,8 +564,10 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size)
|
||||
struct annotation_line *al;
|
||||
|
||||
al = annotated_source__get_line(notes->src, offset);
|
||||
if (al)
|
||||
if (al) {
|
||||
zfree(&al->cycles);
|
||||
zfree(&al->br_cntr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1960,6 +1978,22 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
|
||||
"Cycle(min/max)");
|
||||
}
|
||||
|
||||
if (annotate_opts.show_br_cntr) {
|
||||
if (show_title) {
|
||||
obj__printf(obj, "%*s ",
|
||||
ANNOTATION__BR_CNTR_WIDTH,
|
||||
"Branch Counter");
|
||||
} else {
|
||||
char *buf;
|
||||
|
||||
if (!annotation_br_cntr_entry(&buf, al->br_cntr_nr, al->br_cntr,
|
||||
al->num_aggr, al->evsel)) {
|
||||
obj__printf(obj, "%*s ", ANNOTATION__BR_CNTR_WIDTH, buf);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (show_title && !*al->line) {
|
||||
ipc_coverage_string(bf, sizeof(bf), notes);
|
||||
obj__printf(obj, "%*s", ANNOTATION__AVG_IPC_WIDTH, bf);
|
||||
@ -2056,7 +2090,7 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
|
||||
annotation__set_index(notes);
|
||||
annotation__mark_jump_targets(notes, sym);
|
||||
|
||||
err = annotation__compute_ipc(notes, size);
|
||||
err = annotation__compute_ipc(notes, size, evsel);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -31,6 +31,7 @@ struct annotated_data_type;
|
||||
#define ANNOTATION__CYCLES_WIDTH 6
|
||||
#define ANNOTATION__MINMAX_CYCLES_WIDTH 19
|
||||
#define ANNOTATION__AVG_IPC_WIDTH 36
|
||||
#define ANNOTATION__BR_CNTR_WIDTH 30
|
||||
#define ANNOTATION_DUMMY_LEN 256
|
||||
|
||||
struct annotation_options {
|
||||
@ -44,6 +45,7 @@ struct annotation_options {
|
||||
show_nr_jumps,
|
||||
show_minmax_cycle,
|
||||
show_asm_raw,
|
||||
show_br_cntr,
|
||||
annotate_src,
|
||||
full_addr;
|
||||
u8 offset_level;
|
||||
@ -104,6 +106,10 @@ struct annotation_line {
|
||||
char *fileloc;
|
||||
char *path;
|
||||
struct cycles_info *cycles;
|
||||
int num_aggr;
|
||||
int br_cntr_nr;
|
||||
u64 *br_cntr;
|
||||
struct evsel *evsel;
|
||||
int jump_sources;
|
||||
u32 idx;
|
||||
int idx_asm;
|
||||
@ -353,6 +359,11 @@ static inline bool annotation_line__filter(struct annotation_line *al)
|
||||
return annotate_opts.hide_src_code && al->offset == -1;
|
||||
}
|
||||
|
||||
static inline u8 annotation__br_cntr_width(void)
|
||||
{
|
||||
return annotate_opts.show_br_cntr ? ANNOTATION__BR_CNTR_WIDTH : 0;
|
||||
}
|
||||
|
||||
void annotation__update_column_widths(struct annotation *notes);
|
||||
void annotation__toggle_full_addr(struct annotation *notes, struct map_symbol *ms);
|
||||
|
||||
|
@ -1015,6 +1015,7 @@ static void annotation_line__exit(struct annotation_line *al)
|
||||
zfree_srcline(&al->path);
|
||||
zfree(&al->line);
|
||||
zfree(&al->cycles);
|
||||
zfree(&al->br_cntr);
|
||||
}
|
||||
|
||||
static size_t disasm_line_size(int nr)
|
||||
|
Loading…
Reference in New Issue
Block a user