perf annotate: Calculate instruction overhead using hashmap
authorNamhyung Kim <namhyung@kernel.org>
Mon, 4 Mar 2024 23:08:13 +0000 (15:08 -0800)
committerNamhyung Kim <namhyung@kernel.org>
Thu, 7 Mar 2024 04:25:20 +0000 (20:25 -0800)
Use annotated_source.samples hashmap instead of addr array in the
struct sym_hist.

Reviewed-by: Ian Rogers <irogers@google.com>
Reviewed-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240304230815.1440583-3-namhyung@kernel.org
tools/perf/ui/gtk/annotate.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h

index 3948612..93ce3d4 100644 (file)
@@ -28,21 +28,29 @@ static const char *const col_names[] = {
 static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
                                 struct disasm_line *dl, int evidx)
 {
+       struct annotation *notes;
        struct sym_hist *symhist;
+       struct sym_hist_entry *entry;
        double percent = 0.0;
        const char *markup;
        int ret = 0;
+       u64 nr_samples = 0;
 
        strcpy(buf, "");
 
        if (dl->al.offset == (s64) -1)
                return 0;
 
-       symhist = annotation__histogram(symbol__annotation(sym), evidx);
-       if (!symbol_conf.event_group && !symhist->addr[dl->al.offset].nr_samples)
+       notes = symbol__annotation(sym);
+       symhist = annotation__histogram(notes, evidx);
+       entry = annotated_source__hist_entry(notes->src, evidx, dl->al.offset);
+       if (entry)
+               nr_samples = entry->nr_samples;
+
+       if (!symbol_conf.event_group && nr_samples == 0)
                return 0;
 
-       percent = 100.0 * symhist->addr[dl->al.offset].nr_samples / symhist->nr_samples;
+       percent = 100.0 * nr_samples / symhist->nr_samples;
 
        markup = perf_gtk__get_percent_color(percent);
        if (markup)
index caaea94..1451699 100644 (file)
@@ -2368,17 +2368,25 @@ out_remove_tmp:
        return err;
 }
 
-static void calc_percent(struct sym_hist *sym_hist,
-                        struct hists *hists,
+static void calc_percent(struct annotation *notes,
+                        struct evsel *evsel,
                         struct annotation_data *data,
                         s64 offset, s64 end)
 {
+       struct hists *hists = evsel__hists(evsel);
+       int evidx = evsel->core.idx;
+       struct sym_hist *sym_hist = annotation__histogram(notes, evidx);
        unsigned int hits = 0;
        u64 period = 0;
 
        while (offset < end) {
-               hits   += sym_hist->addr[offset].nr_samples;
-               period += sym_hist->addr[offset].period;
+               struct sym_hist_entry *entry;
+
+               entry = annotated_source__hist_entry(notes->src, evidx, offset);
+               if (entry) {
+                       hits   += entry->nr_samples;
+                       period += entry->period;
+               }
                ++offset;
        }
 
@@ -2415,16 +2423,13 @@ static void annotation__calc_percent(struct annotation *notes,
                end  = next ? next->offset : len;
 
                for_each_group_evsel(evsel, leader) {
-                       struct hists *hists = evsel__hists(evsel);
                        struct annotation_data *data;
-                       struct sym_hist *sym_hist;
 
                        BUG_ON(i >= al->data_nr);
 
-                       sym_hist = annotation__histogram(notes, evsel->core.idx);
                        data = &al->data[i++];
 
-                       calc_percent(sym_hist, hists, data, al->offset, end);
+                       calc_percent(notes, evsel, data, al->offset, end);
                }
        }
 }
@@ -2619,14 +2624,19 @@ static void print_summary(struct rb_root *root, const char *filename)
 
 static void symbol__annotate_hits(struct symbol *sym, struct evsel *evsel)
 {
+       int evidx = evsel->core.idx;
        struct annotation *notes = symbol__annotation(sym);
-       struct sym_hist *h = annotation__histogram(notes, evsel->core.idx);
+       struct sym_hist *h = annotation__histogram(notes, evidx);
        u64 len = symbol__size(sym), offset;
 
-       for (offset = 0; offset < len; ++offset)
-               if (h->addr[offset].nr_samples != 0)
+       for (offset = 0; offset < len; ++offset) {
+               struct sym_hist_entry *entry;
+
+               entry = annotated_source__hist_entry(notes->src, evidx, offset);
+               if (entry && entry->nr_samples != 0)
                        printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
-                              sym->start + offset, h->addr[offset].nr_samples);
+                              sym->start + offset, entry->nr_samples);
+       }
        printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
 }
 
@@ -2855,8 +2865,14 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
 
        h->nr_samples = 0;
        for (offset = 0; offset < len; ++offset) {
-               h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
-               h->nr_samples += h->addr[offset].nr_samples;
+               struct sym_hist_entry *entry;
+
+               entry = annotated_source__hist_entry(notes->src, evidx, offset);
+               if (entry == NULL)
+                       continue;
+
+               entry->nr_samples = entry->nr_samples * 7 / 8;
+               h->nr_samples += entry->nr_samples;
        }
 }
 
index a2b0c82..3362980 100644 (file)
@@ -356,6 +356,17 @@ static inline struct sym_hist *annotation__histogram(struct annotation *notes, i
        return annotated_source__histogram(notes->src, idx);
 }
 
+static inline struct sym_hist_entry *
+annotated_source__hist_entry(struct annotated_source *src, int idx, u64 offset)
+{
+       struct sym_hist_entry *entry;
+       long key = offset << 16 | idx;
+
+       if (!hashmap__find(src->samples, key, &entry))
+               return NULL;
+       return entry;
+}
+
 static inline struct annotation *symbol__annotation(struct symbol *sym)
 {
        return (void *)sym - symbol_conf.priv_size;