mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
perf annotate: Add --insn-stat option for debugging
This is for a debugging purpose. It'd be useful to see per-instrucion level success/failure stats. $ perf annotate --data-type --insn-stat Annotate Instruction stats total 264, ok 143 (54.2%), bad 121 (45.8%) Name : Good Bad ----------------------------------------------------------- movq : 45 31 movl : 22 11 popq : 0 19 cmpl : 16 3 addq : 8 7 cmpq : 11 3 cmpxchgl : 3 7 cmpxchgq : 8 0 incl : 3 3 movzbl : 4 2 incq : 4 2 decl : 6 0 ... Committer notes: So these are about being able to find the type for accesses from these instructions, we should improve the naming, but it is for debugging, we can improve this later: @@ -3726,6 +3759,10 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he) continue; mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset); + if (mem_type) + istat->good++; + else + istat->bad++; Signed-off-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: Jiri Olsa <jolsa@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: linux-toolchains@vger.kernel.org Cc: linux-trace-devel@vger.kernel.org Link: https://lore.kernel.org/r/20231213001323.718046-18-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
61a9741e9f
commit
58824fa008
@ -58,6 +58,7 @@ struct perf_annotate {
|
||||
bool group_set;
|
||||
bool data_type;
|
||||
bool type_stat;
|
||||
bool insn_stat;
|
||||
float min_percent;
|
||||
const char *sym_hist_filter;
|
||||
const char *cpu_list;
|
||||
@ -434,6 +435,42 @@ static void print_annotate_data_stat(struct annotated_data_stat *s)
|
||||
#undef PRINT_STAT
|
||||
}
|
||||
|
||||
static void print_annotate_item_stat(struct list_head *head, const char *title)
|
||||
{
|
||||
struct annotated_item_stat *istat, *pos, *iter;
|
||||
int total_good, total_bad, total;
|
||||
int sum1, sum2;
|
||||
LIST_HEAD(tmp);
|
||||
|
||||
/* sort the list by count */
|
||||
list_splice_init(head, &tmp);
|
||||
total_good = total_bad = 0;
|
||||
|
||||
list_for_each_entry_safe(istat, pos, &tmp, list) {
|
||||
total_good += istat->good;
|
||||
total_bad += istat->bad;
|
||||
sum1 = istat->good + istat->bad;
|
||||
|
||||
list_for_each_entry(iter, head, list) {
|
||||
sum2 = iter->good + iter->bad;
|
||||
if (sum1 > sum2)
|
||||
break;
|
||||
}
|
||||
list_move_tail(&istat->list, &iter->list);
|
||||
}
|
||||
total = total_good + total_bad;
|
||||
|
||||
printf("Annotate %s stats\n", title);
|
||||
printf("total %d, ok %d (%.1f%%), bad %d (%.1f%%)\n\n", total,
|
||||
total_good, 100.0 * total_good / (total ?: 1),
|
||||
total_bad, 100.0 * total_bad / (total ?: 1));
|
||||
printf(" %-10s: %5s %5s\n", "Name", "Good", "Bad");
|
||||
printf("-----------------------------------------------------------\n");
|
||||
list_for_each_entry(istat, head, list)
|
||||
printf(" %-10s: %5d %5d\n", istat->name, istat->good, istat->bad);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void hists__find_annotations(struct hists *hists,
|
||||
struct evsel *evsel,
|
||||
struct perf_annotate *ann)
|
||||
@ -443,6 +480,8 @@ static void hists__find_annotations(struct hists *hists,
|
||||
|
||||
if (ann->type_stat)
|
||||
print_annotate_data_stat(&ann_data_stat);
|
||||
if (ann->insn_stat)
|
||||
print_annotate_item_stat(&ann_insn_stat, "Instruction");
|
||||
|
||||
while (nd) {
|
||||
struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
|
||||
@ -792,6 +831,8 @@ int cmd_annotate(int argc, const char **argv)
|
||||
parse_data_type),
|
||||
OPT_BOOLEAN(0, "type-stat", &annotate.type_stat,
|
||||
"Show stats for the data type annotation"),
|
||||
OPT_BOOLEAN(0, "insn-stat", &annotate.insn_stat,
|
||||
"Show instruction stats for the data type annotation"),
|
||||
OPT_END()
|
||||
};
|
||||
int ret;
|
||||
|
@ -105,6 +105,7 @@ static struct ins_ops ret_ops;
|
||||
|
||||
/* Data type collection debug statistics */
|
||||
struct annotated_data_stat ann_data_stat;
|
||||
LIST_HEAD(ann_insn_stat);
|
||||
|
||||
static int arch__grow_instructions(struct arch *arch)
|
||||
{
|
||||
@ -3665,6 +3666,30 @@ static struct disasm_line *find_disasm_line(struct symbol *sym, u64 ip)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct annotated_item_stat *annotate_data_stat(struct list_head *head,
|
||||
const char *name)
|
||||
{
|
||||
struct annotated_item_stat *istat;
|
||||
|
||||
list_for_each_entry(istat, head, list) {
|
||||
if (!strcmp(istat->name, name))
|
||||
return istat;
|
||||
}
|
||||
|
||||
istat = zalloc(sizeof(*istat));
|
||||
if (istat == NULL)
|
||||
return NULL;
|
||||
|
||||
istat->name = strdup(name);
|
||||
if (istat->name == NULL) {
|
||||
free(istat);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_add_tail(&istat->list, head);
|
||||
return istat;
|
||||
}
|
||||
|
||||
/**
|
||||
* hist_entry__get_data_type - find data type for given hist entry
|
||||
* @he: hist entry
|
||||
@ -3683,6 +3708,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
|
||||
struct annotated_insn_loc loc;
|
||||
struct annotated_op_loc *op_loc;
|
||||
struct annotated_data_type *mem_type;
|
||||
struct annotated_item_stat *istat;
|
||||
u64 ip = he->ip;
|
||||
int i;
|
||||
|
||||
@ -3716,8 +3742,15 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
istat = annotate_data_stat(&ann_insn_stat, dl->ins.name);
|
||||
if (istat == NULL) {
|
||||
ann_data_stat.no_insn++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (annotate_get_insn_location(arch, dl, &loc) < 0) {
|
||||
ann_data_stat.no_insn_ops++;
|
||||
istat->bad++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -3726,6 +3759,10 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
|
||||
continue;
|
||||
|
||||
mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset);
|
||||
if (mem_type)
|
||||
istat->good++;
|
||||
else
|
||||
istat->bad++;
|
||||
|
||||
if (symbol_conf.annotate_data_sample) {
|
||||
annotated_data_type__update_samples(mem_type, evsel,
|
||||
@ -3738,5 +3775,6 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
|
||||
}
|
||||
|
||||
ann_data_stat.no_mem_ops++;
|
||||
istat->bad++;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -479,4 +479,12 @@ int annotate_get_insn_location(struct arch *arch, struct disasm_line *dl,
|
||||
/* Returns a data type from the sample instruction (if any) */
|
||||
struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he);
|
||||
|
||||
struct annotated_item_stat {
|
||||
struct list_head list;
|
||||
char *name;
|
||||
int good;
|
||||
int bad;
|
||||
};
|
||||
extern struct list_head ann_insn_stat;
|
||||
|
||||
#endif /* __PERF_ANNOTATE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user