Commit e6952dce authored by Kan Liang's avatar Kan Liang Committed by Arnaldo Carvalho de Melo

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: default avatarTinghao Zhang <tinghao.zhang@intel.com>
Reviewed-by: default avatarAndi Kleen <ak@linux.intel.com>
Signed-off-by: default avatarKan Liang <kan.liang@linux.intel.com>
Acked-by: default avatarNamhyung 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.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 20d6f555
...@@ -927,11 +927,15 @@ int cmd_annotate(int argc, const char **argv) ...@@ -927,11 +927,15 @@ int cmd_annotate(int argc, const char **argv)
sort_order = "dso,symbol"; sort_order = "dso,symbol";
/* /*
* Set SORT_MODE__BRANCH so that annotate display IPC/Cycle * Set SORT_MODE__BRANCH so that annotate displays IPC/Cycle and
* if branch info is in perf data in TUI mode. * 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; sort__mode = SORT_MODE__BRANCH;
if (annotate.session->evlist->nr_br_cntr > 0)
annotate_opts.show_br_cntr = true;
}
if (setup_sorting(NULL) < 0) if (setup_sorting(NULL) < 0)
usage_with_options(annotate_usage, options); usage_with_options(annotate_usage, options);
......
...@@ -156,6 +156,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) ...@@ -156,6 +156,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
struct symbol *sym = ms->sym; struct symbol *sym = ms->sym;
struct annotation *notes = symbol__annotation(sym); struct annotation *notes = symbol__annotation(sym);
u8 pcnt_width = annotation__pcnt_width(notes); u8 pcnt_width = annotation__pcnt_width(notes);
u8 cntr_width = annotation__br_cntr_width();
int width; int width;
int diff = 0; int diff = 0;
...@@ -205,13 +206,13 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) ...@@ -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__set_color(browser, HE_COLORSET_JUMP_ARROWS);
__ui_browser__line_arrow(browser, __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); from, to);
diff = is_fused(ab, cursor); diff = is_fused(ab, cursor);
if (diff > 0) { if (diff > 0) {
ui_browser__mark_fused(browser, 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); from - diff, diff, to > from);
} }
} }
...@@ -714,6 +715,7 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -714,6 +715,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
struct annotation *notes = symbol__annotation(ms->sym); struct annotation *notes = symbol__annotation(ms->sym);
const char *help = "Press 'h' for help on key bindings"; const char *help = "Press 'h' for help on key bindings";
int delay_secs = hbt ? hbt->refresh : 0; int delay_secs = hbt ? hbt->refresh : 0;
char *br_cntr_text = NULL;
char title[256]; char title[256];
int key; int key;
...@@ -730,6 +732,8 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -730,6 +732,8 @@ static int annotate_browser__run(struct annotate_browser *browser,
nd = browser->curr_hot; nd = browser->curr_hot;
annotation_br_cntr_abbr_list(&br_cntr_text, evsel, false);
while (1) { while (1) {
key = ui_browser__run(&browser->b, delay_secs); key = ui_browser__run(&browser->b, delay_secs);
...@@ -796,6 +800,7 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -796,6 +800,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
"r Run available scripts\n" "r Run available scripts\n"
"p Toggle percent type [local/global]\n" "p Toggle percent type [local/global]\n"
"b Toggle percent base [period/hits]\n" "b Toggle percent base [period/hits]\n"
"B Branch counter abbr list (Optional)\n"
"? Search string backwards\n" "? Search string backwards\n"
"f Toggle showing offsets to full address\n"); "f Toggle showing offsets to full address\n");
continue; continue;
...@@ -904,6 +909,14 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -904,6 +909,14 @@ static int annotate_browser__run(struct annotate_browser *browser,
hists__scnprintf_title(hists, title, sizeof(title)); hists__scnprintf_title(hists, title, sizeof(title));
annotate_browser__show(&browser->b, title, help); annotate_browser__show(&browser->b, title, help);
continue; 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': case 'f':
annotation__toggle_full_addr(notes, ms); annotation__toggle_full_addr(notes, ms);
continue; continue;
...@@ -923,6 +936,7 @@ static int annotate_browser__run(struct annotate_browser *browser, ...@@ -923,6 +936,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
} }
out: out:
ui_browser__hide(&browser->b); ui_browser__hide(&browser->b);
free(br_cntr_text);
return key; return key;
} }
......
...@@ -3705,7 +3705,8 @@ int block_hists_tui_browse(struct block_hist *bh, struct evsel *evsel, ...@@ -3705,7 +3705,8 @@ int block_hists_tui_browse(struct block_hist *bh, struct evsel *evsel,
memset(&action, 0, sizeof(action)); 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) { while (1) {
key = hist_browser__run(browser, "? - help", true, 0); key = hist_browser__run(browser, "? - help", true, 0);
......
...@@ -501,8 +501,10 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 ...@@ -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; int err = 0;
s64 offset; s64 offset;
...@@ -537,6 +539,20 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size) ...@@ -537,6 +539,20 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size)
al->cycles->max = ch->cycles_max; al->cycles->max = ch->cycles_max;
al->cycles->min = ch->cycles_min; 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, &notes->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) ...@@ -548,8 +564,10 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size)
struct annotation_line *al; struct annotation_line *al;
al = annotated_source__get_line(notes->src, offset); al = annotated_source__get_line(notes->src, offset);
if (al) if (al) {
zfree(&al->cycles); zfree(&al->cycles);
zfree(&al->br_cntr);
}
} }
} }
} }
...@@ -1960,6 +1978,22 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati ...@@ -1960,6 +1978,22 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
"Cycle(min/max)"); "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) { if (show_title && !*al->line) {
ipc_coverage_string(bf, sizeof(bf), notes); ipc_coverage_string(bf, sizeof(bf), notes);
obj__printf(obj, "%*s", ANNOTATION__AVG_IPC_WIDTH, bf); obj__printf(obj, "%*s", ANNOTATION__AVG_IPC_WIDTH, bf);
...@@ -2056,7 +2090,7 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel, ...@@ -2056,7 +2090,7 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
annotation__set_index(notes); annotation__set_index(notes);
annotation__mark_jump_targets(notes, sym); annotation__mark_jump_targets(notes, sym);
err = annotation__compute_ipc(notes, size); err = annotation__compute_ipc(notes, size, evsel);
if (err) if (err)
return err; return err;
......
...@@ -31,6 +31,7 @@ struct annotated_data_type; ...@@ -31,6 +31,7 @@ struct annotated_data_type;
#define ANNOTATION__CYCLES_WIDTH 6 #define ANNOTATION__CYCLES_WIDTH 6
#define ANNOTATION__MINMAX_CYCLES_WIDTH 19 #define ANNOTATION__MINMAX_CYCLES_WIDTH 19
#define ANNOTATION__AVG_IPC_WIDTH 36 #define ANNOTATION__AVG_IPC_WIDTH 36
#define ANNOTATION__BR_CNTR_WIDTH 30
#define ANNOTATION_DUMMY_LEN 256 #define ANNOTATION_DUMMY_LEN 256
struct annotation_options { struct annotation_options {
...@@ -44,6 +45,7 @@ struct annotation_options { ...@@ -44,6 +45,7 @@ struct annotation_options {
show_nr_jumps, show_nr_jumps,
show_minmax_cycle, show_minmax_cycle,
show_asm_raw, show_asm_raw,
show_br_cntr,
annotate_src, annotate_src,
full_addr; full_addr;
u8 offset_level; u8 offset_level;
...@@ -104,6 +106,10 @@ struct annotation_line { ...@@ -104,6 +106,10 @@ struct annotation_line {
char *fileloc; char *fileloc;
char *path; char *path;
struct cycles_info *cycles; struct cycles_info *cycles;
int num_aggr;
int br_cntr_nr;
u64 *br_cntr;
struct evsel *evsel;
int jump_sources; int jump_sources;
u32 idx; u32 idx;
int idx_asm; int idx_asm;
...@@ -353,6 +359,11 @@ static inline bool annotation_line__filter(struct annotation_line *al) ...@@ -353,6 +359,11 @@ static inline bool annotation_line__filter(struct annotation_line *al)
return annotate_opts.hide_src_code && al->offset == -1; 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__update_column_widths(struct annotation *notes);
void annotation__toggle_full_addr(struct annotation *notes, struct map_symbol *ms); 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) ...@@ -1015,6 +1015,7 @@ static void annotation_line__exit(struct annotation_line *al)
zfree_srcline(&al->path); zfree_srcline(&al->path);
zfree(&al->line); zfree(&al->line);
zfree(&al->cycles); zfree(&al->cycles);
zfree(&al->br_cntr);
} }
static size_t disasm_line_size(int nr) static size_t disasm_line_size(int nr)
......
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