]> git.itanic.dy.fi Git - linux-stable/commitdiff
perf annotate: Add --insn-stat option for debugging
authorNamhyung Kim <namhyung@kernel.org>
Wed, 13 Dec 2023 00:13:23 +0000 (16:13 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Sun, 24 Dec 2023 01:40:17 +0000 (22:40 -0300)
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>
tools/perf/builtin-annotate.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h

index 55f97ab1395ba28464c4835e16569acdf195b042..6c1cc797692d949f6fc07bb195007ecfad536dd6 100644 (file)
@@ -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;
index 9870257ce21e7772c8fd7ac6f75889493e9c5f68..9b70ab110ce79f24da580611f1a2098726f1ae12 100644 (file)
@@ -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;
 }
index 6c75b28322860b7a7e389610804bac04f09dd91a..dba50762c6e807198880909a7a058e78bc7f9e21 100644 (file)
@@ -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 */