Commit b7f87e32 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf annotate: Split branch stack cycles info from 'struct annotation'

The cycles info is only meaningful when sample has branch stacks.  To
save the memory for normal cases, move those fields to a new 'struct
annotated_branch' and dynamically allocate it when needed.  Also move
cycles_hist from annotated_source as it's related here.
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20231103191907.54531-3-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent de2c7eb5
...@@ -810,7 +810,6 @@ static __maybe_unused void annotated_source__delete(struct annotated_source *src ...@@ -810,7 +810,6 @@ static __maybe_unused void annotated_source__delete(struct annotated_source *src
if (src == NULL) if (src == NULL)
return; return;
zfree(&src->histograms); zfree(&src->histograms);
zfree(&src->cycles_hist);
free(src); free(src);
} }
...@@ -845,18 +844,6 @@ static int annotated_source__alloc_histograms(struct annotated_source *src, ...@@ -845,18 +844,6 @@ static int annotated_source__alloc_histograms(struct annotated_source *src,
return src->histograms ? 0 : -1; return src->histograms ? 0 : -1;
} }
/* The cycles histogram is lazily allocated. */
static int symbol__alloc_hist_cycles(struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
const size_t size = symbol__size(sym);
notes->src->cycles_hist = calloc(size, sizeof(struct cyc_hist));
if (notes->src->cycles_hist == NULL)
return -1;
return 0;
}
void symbol__annotate_zero_histograms(struct symbol *sym) void symbol__annotate_zero_histograms(struct symbol *sym)
{ {
struct annotation *notes = symbol__annotation(sym); struct annotation *notes = symbol__annotation(sym);
...@@ -865,9 +852,10 @@ void symbol__annotate_zero_histograms(struct symbol *sym) ...@@ -865,9 +852,10 @@ void symbol__annotate_zero_histograms(struct symbol *sym)
if (notes->src != NULL) { if (notes->src != NULL) {
memset(notes->src->histograms, 0, memset(notes->src->histograms, 0,
notes->src->nr_histograms * notes->src->sizeof_sym_hist); notes->src->nr_histograms * notes->src->sizeof_sym_hist);
if (notes->src->cycles_hist) }
memset(notes->src->cycles_hist, 0, if (notes->branch && notes->branch->cycles_hist) {
symbol__size(sym) * sizeof(struct cyc_hist)); memset(notes->branch->cycles_hist, 0,
symbol__size(sym) * sizeof(struct cyc_hist));
} }
annotation__unlock(notes); annotation__unlock(notes);
} }
...@@ -958,23 +946,33 @@ static int __symbol__inc_addr_samples(struct map_symbol *ms, ...@@ -958,23 +946,33 @@ static int __symbol__inc_addr_samples(struct map_symbol *ms,
return 0; return 0;
} }
static struct annotated_branch *annotation__get_branch(struct annotation *notes)
{
if (notes == NULL)
return NULL;
if (notes->branch == NULL)
notes->branch = zalloc(sizeof(*notes->branch));
return notes->branch;
}
static struct cyc_hist *symbol__cycles_hist(struct symbol *sym) static struct cyc_hist *symbol__cycles_hist(struct symbol *sym)
{ {
struct annotation *notes = symbol__annotation(sym); struct annotation *notes = symbol__annotation(sym);
struct annotated_branch *branch;
if (notes->src == NULL) { branch = annotation__get_branch(notes);
notes->src = annotated_source__new(); if (branch == NULL)
if (notes->src == NULL) return NULL;
return NULL;
goto alloc_cycles_hist; if (branch->cycles_hist == NULL) {
} const size_t size = symbol__size(sym);
if (!notes->src->cycles_hist) { branch->cycles_hist = calloc(size, sizeof(struct cyc_hist));
alloc_cycles_hist:
symbol__alloc_hist_cycles(sym);
} }
return notes->src->cycles_hist; return branch->cycles_hist;
} }
struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists) struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists)
...@@ -1083,6 +1081,14 @@ static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64 ...@@ -1083,6 +1081,14 @@ static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64
return n_insn; return n_insn;
} }
static void annotated_branch__delete(struct annotated_branch *branch)
{
if (branch) {
zfree(&branch->cycles_hist);
free(branch);
}
}
static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch) static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch)
{ {
unsigned n_insn; unsigned n_insn;
...@@ -1091,6 +1097,7 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 ...@@ -1091,6 +1097,7 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64
n_insn = annotation__count_insn(notes, start, end); n_insn = annotation__count_insn(notes, start, end);
if (n_insn && ch->num && ch->cycles) { if (n_insn && ch->num && ch->cycles) {
struct annotated_branch *branch;
float ipc = n_insn / ((double)ch->cycles / (double)ch->num); float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
/* Hide data when there are too many overlaps. */ /* Hide data when there are too many overlaps. */
...@@ -1106,10 +1113,11 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 ...@@ -1106,10 +1113,11 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64
} }
} }
if (cover_insn) { branch = annotation__get_branch(notes);
notes->hit_cycles += ch->cycles; if (cover_insn && branch) {
notes->hit_insn += n_insn * ch->num; branch->hit_cycles += ch->cycles;
notes->cover_insn += cover_insn; branch->hit_insn += n_insn * ch->num;
branch->cover_insn += cover_insn;
} }
} }
} }
...@@ -1119,19 +1127,19 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size) ...@@ -1119,19 +1127,19 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size)
int err = 0; int err = 0;
s64 offset; s64 offset;
if (!notes->src || !notes->src->cycles_hist) if (!notes->branch || !notes->branch->cycles_hist)
return 0; return 0;
notes->total_insn = annotation__count_insn(notes, 0, size - 1); notes->branch->total_insn = annotation__count_insn(notes, 0, size - 1);
notes->hit_cycles = 0; notes->branch->hit_cycles = 0;
notes->hit_insn = 0; notes->branch->hit_insn = 0;
notes->cover_insn = 0; notes->branch->cover_insn = 0;
annotation__lock(notes); annotation__lock(notes);
for (offset = size - 1; offset >= 0; --offset) { for (offset = size - 1; offset >= 0; --offset) {
struct cyc_hist *ch; struct cyc_hist *ch;
ch = &notes->src->cycles_hist[offset]; ch = &notes->branch->cycles_hist[offset];
if (ch && ch->cycles) { if (ch && ch->cycles) {
struct annotation_line *al; struct annotation_line *al;
...@@ -1150,13 +1158,12 @@ static int annotation__compute_ipc(struct annotation *notes, size_t size) ...@@ -1150,13 +1158,12 @@ 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;
} }
notes->have_cycles = true;
} }
} }
if (err) { if (err) {
while (++offset < (s64)size) { while (++offset < (s64)size) {
struct cyc_hist *ch = &notes->src->cycles_hist[offset]; struct cyc_hist *ch = &notes->branch->cycles_hist[offset];
if (ch && ch->cycles) { if (ch && ch->cycles) {
struct annotation_line *al = notes->offsets[offset]; struct annotation_line *al = notes->offsets[offset];
...@@ -1322,6 +1329,7 @@ int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool r ...@@ -1322,6 +1329,7 @@ int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool r
void annotation__exit(struct annotation *notes) void annotation__exit(struct annotation *notes)
{ {
annotated_source__delete(notes->src); annotated_source__delete(notes->src);
annotated_branch__delete(notes->branch);
} }
static struct sharded_mutex *sharded_mutex; static struct sharded_mutex *sharded_mutex;
...@@ -3075,13 +3083,14 @@ static void disasm_line__write(struct disasm_line *dl, struct annotation *notes, ...@@ -3075,13 +3083,14 @@ static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
static void ipc_coverage_string(char *bf, int size, struct annotation *notes) static void ipc_coverage_string(char *bf, int size, struct annotation *notes)
{ {
double ipc = 0.0, coverage = 0.0; double ipc = 0.0, coverage = 0.0;
struct annotated_branch *branch = annotation__get_branch(notes);
if (notes->hit_cycles) if (branch && branch->hit_cycles)
ipc = notes->hit_insn / ((double)notes->hit_cycles); ipc = branch->hit_insn / ((double)branch->hit_cycles);
if (notes->total_insn) { if (branch && branch->total_insn) {
coverage = notes->cover_insn * 100.0 / coverage = branch->cover_insn * 100.0 /
((double)notes->total_insn); ((double)branch->total_insn);
} }
scnprintf(bf, size, "(Average IPC: %.2f, IPC Coverage: %.1f%%)", scnprintf(bf, size, "(Average IPC: %.2f, IPC Coverage: %.1f%%)",
...@@ -3106,7 +3115,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati ...@@ -3106,7 +3115,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
int printed; int printed;
if (first_line && (al->offset == -1 || percent_max == 0.0)) { if (first_line && (al->offset == -1 || percent_max == 0.0)) {
if (notes->have_cycles && al->cycles) { if (notes->branch && al->cycles) {
if (al->cycles->ipc == 0.0 && al->cycles->avg == 0) if (al->cycles->ipc == 0.0 && al->cycles->avg == 0)
show_title = true; show_title = true;
} else } else
...@@ -3143,7 +3152,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati ...@@ -3143,7 +3152,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
} }
} }
if (notes->have_cycles) { if (notes->branch) {
if (al->cycles && al->cycles->ipc) if (al->cycles && al->cycles->ipc)
obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->cycles->ipc); obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->cycles->ipc);
else if (!show_title) else if (!show_title)
......
...@@ -271,17 +271,20 @@ struct annotated_source { ...@@ -271,17 +271,20 @@ struct annotated_source {
struct list_head source; struct list_head source;
int nr_histograms; int nr_histograms;
size_t sizeof_sym_hist; size_t sizeof_sym_hist;
struct cyc_hist *cycles_hist;
struct sym_hist *histograms; struct sym_hist *histograms;
}; };
struct LOCKABLE annotation { struct annotated_branch {
u64 max_coverage;
u64 start;
u64 hit_cycles; u64 hit_cycles;
u64 hit_insn; u64 hit_insn;
unsigned int total_insn; unsigned int total_insn;
unsigned int cover_insn; unsigned int cover_insn;
struct cyc_hist *cycles_hist;
};
struct LOCKABLE annotation {
u64 max_coverage;
u64 start;
struct annotation_options *options; struct annotation_options *options;
struct annotation_line **offsets; struct annotation_line **offsets;
int nr_events; int nr_events;
...@@ -297,8 +300,8 @@ struct LOCKABLE annotation { ...@@ -297,8 +300,8 @@ struct LOCKABLE annotation {
u8 max_addr; u8 max_addr;
u8 max_ins_name; u8 max_ins_name;
} widths; } widths;
bool have_cycles;
struct annotated_source *src; struct annotated_source *src;
struct annotated_branch *branch;
}; };
static inline void annotation__init(struct annotation *notes __maybe_unused) static inline void annotation__init(struct annotation *notes __maybe_unused)
...@@ -312,10 +315,10 @@ bool annotation__trylock(struct annotation *notes) EXCLUSIVE_TRYLOCK_FUNCTION(tr ...@@ -312,10 +315,10 @@ bool annotation__trylock(struct annotation *notes) EXCLUSIVE_TRYLOCK_FUNCTION(tr
static inline int annotation__cycles_width(struct annotation *notes) static inline int annotation__cycles_width(struct annotation *notes)
{ {
if (notes->have_cycles && notes->options->show_minmax_cycle) if (notes->branch && notes->options->show_minmax_cycle)
return ANNOTATION__IPC_WIDTH + ANNOTATION__MINMAX_CYCLES_WIDTH; return ANNOTATION__IPC_WIDTH + ANNOTATION__MINMAX_CYCLES_WIDTH;
return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0; return notes->branch ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
} }
static inline int annotation__pcnt_width(struct annotation *notes) static inline int annotation__pcnt_width(struct annotation *notes)
......
...@@ -129,9 +129,9 @@ int block_info__process_sym(struct hist_entry *he, struct block_hist *bh, ...@@ -129,9 +129,9 @@ int block_info__process_sym(struct hist_entry *he, struct block_hist *bh,
al.sym = he->ms.sym; al.sym = he->ms.sym;
notes = symbol__annotation(he->ms.sym); notes = symbol__annotation(he->ms.sym);
if (!notes || !notes->src || !notes->src->cycles_hist) if (!notes || !notes->branch || !notes->branch->cycles_hist)
return 0; return 0;
ch = notes->src->cycles_hist; ch = notes->branch->cycles_hist;
for (unsigned int i = 0; i < symbol__size(he->ms.sym); i++) { for (unsigned int i = 0; i < symbol__size(he->ms.sym); i++) {
if (ch[i].num_aggr) { if (ch[i].num_aggr) {
struct block_info *bi; struct block_info *bi;
......
...@@ -583,21 +583,21 @@ static int hist_entry__sym_ipc_snprintf(struct hist_entry *he, char *bf, ...@@ -583,21 +583,21 @@ static int hist_entry__sym_ipc_snprintf(struct hist_entry *he, char *bf,
{ {
struct symbol *sym = he->ms.sym; struct symbol *sym = he->ms.sym;
struct annotation *notes; struct annotated_branch *branch;
double ipc = 0.0, coverage = 0.0; double ipc = 0.0, coverage = 0.0;
char tmp[64]; char tmp[64];
if (!sym) if (!sym)
return repsep_snprintf(bf, size, "%-*s", width, "-"); return repsep_snprintf(bf, size, "%-*s", width, "-");
notes = symbol__annotation(sym); branch = symbol__annotation(sym)->branch;
if (notes->hit_cycles) if (branch && branch->hit_cycles)
ipc = notes->hit_insn / ((double)notes->hit_cycles); ipc = branch->hit_insn / ((double)branch->hit_cycles);
if (notes->total_insn) { if (branch && branch->total_insn) {
coverage = notes->cover_insn * 100.0 / coverage = branch->cover_insn * 100.0 /
((double)notes->total_insn); ((double)branch->total_insn);
} }
snprintf(tmp, sizeof(tmp), "%-5.2f [%5.1f%%]", ipc, coverage); snprintf(tmp, sizeof(tmp), "%-5.2f [%5.1f%%]", ipc, coverage);
......
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