mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
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";
|
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)
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
"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 @@ show_sup_ins:
|
||||||
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 @@ show_sup_ins:
|
||||||
}
|
}
|
||||||
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,
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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, ¬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;
|
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
|
||||||
"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,
|
||||||
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;
|
||||||
#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 {
|
||||||
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 {
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user