perf annotate: Support multiple histograms in annotation
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 4 Feb 2011 15:43:24 +0000 (13:43 -0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Sat, 5 Feb 2011 14:28:48 +0000 (12:28 -0200)
The perf annotate tool continues aggregating everything on just one
histograms, but to support the top model add support for one histogram
perf evsel in the evlist.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-annotate.c
tools/perf/builtin-report.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/ui/browsers/annotate.c
tools/perf/util/ui/browsers/hists.c

index 9072ef44cfcb5f9b87622ce8a2bc70a8d39a73ba..f3e44231b10d8dcb06fa35abe18014c4dbe7f34b 100644 (file)
@@ -57,7 +57,18 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
        if (he == NULL)
                return -ENOMEM;
 
-       return hist_entry__inc_addr_samples(he, al->addr);
+       if (he->ms.sym != NULL) {
+               /*
+                * All aggregated on the first sym_hist.
+                */
+               struct annotation *notes = symbol__annotation(he->ms.sym);
+               if (notes->histograms == NULL && symbol__alloc_hist(he->ms.sym, 1) < 0)
+                       return -ENOMEM;
+
+               return hist_entry__inc_addr_samples(he, 0, al->addr);
+       }
+
+       return 0;
 }
 
 static int process_sample_event(union perf_event *event,
@@ -81,9 +92,9 @@ static int process_sample_event(union perf_event *event,
        return 0;
 }
 
-static int hist_entry__tty_annotate(struct hist_entry *he)
+static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
 {
-       return symbol__tty_annotate(he->ms.sym, he->ms.map,
+       return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
                                    print_line, full_paths);
 }
 
@@ -100,7 +111,7 @@ static void hists__find_annotations(struct hists *self)
                        goto find_next;
 
                notes = symbol__annotation(he->ms.sym);
-               if (notes->histogram == NULL) {
+               if (notes->histograms == NULL) {
 find_next:
                        if (key == KEY_LEFT)
                                nd = rb_prev(nd);
@@ -110,7 +121,8 @@ find_next:
                }
 
                if (use_browser > 0) {
-                       key = hist_entry__tui_annotate(he);
+                       /* For now all is aggregated on the first */
+                       key = hist_entry__tui_annotate(he, 0);
                        switch (key) {
                        case KEY_RIGHT:
                                next = rb_next(nd);
@@ -125,15 +137,16 @@ find_next:
                        if (next != NULL)
                                nd = next;
                } else {
-                       hist_entry__tty_annotate(he);
+                       /* For now all is aggregated on the first */
+                       hist_entry__tty_annotate(he, 0);
                        nd = rb_next(nd);
                        /*
                         * Since we have a hist_entry per IP for the same
                         * symbol, free he->ms.sym->histogram to signal we already
                         * processed this symbol.
                         */
-                       free(notes->histogram);
-                       notes->histogram = NULL;
+                       free(notes->histograms);
+                       notes->histograms = NULL;
                }
        }
 }
index 91e4cdba933beb4f1bb87e3bc885318da030b6d0..de06bf55efffafd5cb11b1126b780ceb4e6b3db5 100644 (file)
@@ -118,8 +118,17 @@ static int perf_session__add_hist_entry(struct perf_session *session,
         * so we don't allocated the extra space needed because the stdio
         * code will not use it.
         */
-       if (use_browser > 0)
-               err = hist_entry__inc_addr_samples(he, al->addr);
+       if (al->sym != NULL && use_browser > 0) {
+               /*
+                * All aggregated on the first sym_hist.
+                */
+               struct annotation *notes = symbol__annotation(he->ms.sym);
+               if (notes->histograms == NULL &&
+                   symbol__alloc_hist(he->ms.sym, 1) < 0)
+                       err = -ENOMEM;
+               else
+                       err = hist_entry__inc_addr_samples(he, 0, al->addr);
+       }
 
        return err;
 }
@@ -349,7 +358,7 @@ static int __cmd_report(void)
        }
 
        if (use_browser > 0)
-               hists__tui_browse_tree(&session->hists_tree, help);
+               hists__tui_browse_tree(&session->hists_tree, help, 0);
        else
                hists__tty_browse_tree(&session->hists_tree, help);
 
index 9b25575b980ca928c4ed58066c79216ef5558d77..7488fe99502ceb0c8a9c3af4032cecf41ab3ce44 100644 (file)
 #include "debug.h"
 #include "annotate.h"
 
-static int symbol__alloc_hist(struct symbol *sym)
+int symbol__alloc_hist(struct symbol *sym, int nevents)
 {
        struct annotation *notes = symbol__annotation(sym);
-       const int size = (sizeof(*notes->histogram) +
-                         (sym->end - sym->start) * sizeof(u64));
 
-       notes->histogram = zalloc(size);
-       return notes->histogram == NULL ? -1 : 0;
+       notes->sizeof_sym_hist = (sizeof(*notes->histograms) +
+                                 (sym->end - sym->start) * sizeof(u64));
+       notes->histograms = calloc(nevents, notes->sizeof_sym_hist);
+       return notes->histograms == NULL ? -1 : 0;
 }
 
-int symbol__inc_addr_samples(struct symbol *sym, struct map *map, u64 addr)
+int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+                            int evidx, u64 addr)
 {
-       unsigned int sym_size, offset;
+       unsigned offset;
        struct annotation *notes;
        struct sym_hist *h;
 
-       if (!sym || !map)
-               return 0;
-
        notes = symbol__annotation(sym);
-       if (notes->histogram == NULL && symbol__alloc_hist(sym) < 0)
+       if (notes->histograms == NULL)
                return -ENOMEM;
 
-       sym_size = sym->end - sym->start;
-       offset = addr - sym->start;
-
        pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
 
-       if (offset >= sym_size)
+       if (addr >= sym->end)
                return 0;
 
-       h = notes->histogram;
+       offset = addr - sym->start;
+       h = annotation__histogram(notes, evidx);
        h->sum++;
        h->addr[offset]++;
 
        pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
-                 "] => %" PRIu64 "\n", sym->start, sym->name,
-                 addr, addr - sym->start, h->addr[offset]);
+                 ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name,
+                 addr, addr - sym->start, evidx, h->addr[offset]);
        return 0;
 }
 
@@ -90,8 +86,8 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
 }
 
 static void objdump_line__print(struct objdump_line *oline,
-                               struct list_head *head,
-                               struct symbol *sym, u64 len)
+                               struct list_head *head, struct symbol *sym,
+                               int evidx, u64 len)
 {
        static const char *prev_line;
        static const char *prev_color;
@@ -103,7 +99,7 @@ static void objdump_line__print(struct objdump_line *oline,
                const char *color;
                struct annotation *notes = symbol__annotation(sym);
                struct source_line *src_line = notes->src_line;
-               struct sym_hist *h = notes->histogram;
+               struct sym_hist *h = annotation__histogram(notes, evidx);
                s64 offset = oline->offset;
                struct objdump_line *next = objdump__get_next_ip_line(head, oline);
 
@@ -328,7 +324,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
 
 /* Get the filename:line for the colored entries */
 static int symbol__get_source_line(struct symbol *sym, struct map *map,
-                                  struct rb_root *root, int len,
+                                  int evidx, struct rb_root *root, int len,
                                   const char *filename)
 {
        u64 start;
@@ -336,7 +332,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
        char cmd[PATH_MAX * 2];
        struct source_line *src_line;
        struct annotation *notes = symbol__annotation(sym);
-       struct sym_hist *h = notes->histogram;
+       struct sym_hist *h = annotation__histogram(notes, evidx);
 
        if (!h->sum)
                return 0;
@@ -409,10 +405,10 @@ static void print_summary(struct rb_root *root, const char *filename)
        }
 }
 
-static void symbol__annotate_hits(struct symbol *sym)
+static void symbol__annotate_hits(struct symbol *sym, int evidx)
 {
        struct annotation *notes = symbol__annotation(sym);
-       struct sym_hist *h = notes->histogram;
+       struct sym_hist *h = annotation__histogram(notes, evidx);
        u64 len = sym->end - sym->start, offset;
 
        for (offset = 0; offset < len; ++offset)
@@ -422,8 +418,8 @@ static void symbol__annotate_hits(struct symbol *sym)
        printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
 }
 
-int symbol__tty_annotate(struct symbol *sym, struct map *map, bool print_lines,
-                        bool full_paths)
+int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
+                        bool print_lines, bool full_paths)
 {
        struct dso *dso = map->dso;
        const char *filename = dso->long_name, *d_filename;
@@ -443,7 +439,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, bool print_lines,
        len = sym->end - sym->start;
 
        if (print_lines) {
-               symbol__get_source_line(sym, map, &source_line, len, filename);
+               symbol__get_source_line(sym, map, evidx, &source_line,
+                                       len, filename);
                print_summary(&source_line, filename);
        }
 
@@ -452,10 +449,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, bool print_lines,
        printf("------------------------------------------------\n");
 
        if (verbose)
-               symbol__annotate_hits(sym);
+               symbol__annotate_hits(sym, evidx);
 
        list_for_each_entry_safe(pos, n, &head, node) {
-               objdump_line__print(pos, &head, sym, len);
+               objdump_line__print(pos, &head, sym, evidx, len);
                list_del(&pos->node);
                objdump_line__free(pos);
        }
index 6e2fbc205299ab009d34cf3ffccc868d02a8d1de..0a5069ca6dd725eac2f765feae773f6f19ae4920 100644 (file)
@@ -28,9 +28,21 @@ struct source_line {
        char            *path;
 };
 
+/** struct annotation - symbols with hits have this attached as in sannotation
+ *
+ * @histogram: Array of addr hit histograms per event being monitored
+ * @src_line: If 'print_lines' is specified, per source code line percentages
+ *
+ * src_line is allocated, percentages calculated and all sorted by percentage
+ * when the annotation is about to be presented, so the percentages are for
+ * one of the entries in the histogram array, i.e. for the event/counter being
+ * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate
+ * returns.
+ */
 struct annotation {
-       struct sym_hist    *histogram;
        struct source_line *src_line;
+       struct sym_hist    *histograms;
+       int                sizeof_sym_hist;
 };
 
 struct sannotation {
@@ -38,28 +50,35 @@ struct sannotation {
        struct symbol     symbol;
 };
 
+static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
+{
+       return ((void *)notes->histograms) + (notes->sizeof_sym_hist * idx);
+}
+
 static inline struct annotation *symbol__annotation(struct symbol *sym)
 {
        struct sannotation *a = container_of(sym, struct sannotation, symbol);
        return &a->annotation;
 }
 
-int symbol__inc_addr_samples(struct symbol *sym, struct map *map, u64 addr);
+int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+                            int evidx, u64 addr);
+int symbol__alloc_hist(struct symbol *sym, int nevents);
 
 int symbol__annotate(struct symbol *sym, struct map *map,
                     struct list_head *head, size_t privsize);
 
-int symbol__tty_annotate(struct symbol *sym, struct map *map,
+int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
                         bool print_lines, bool full_paths);
 
 #ifdef NO_NEWT_SUPPORT
 static inline int symbol__tui_annotate(symbol *sym __used,
-                                      struct map *map __used)
+                                      struct map *map __used, int evidx __used)
 {
        return 0;
 }
 #else
-int symbol__tui_annotate(struct symbol *sym, struct map *map);
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx);
 #endif
 
 #endif /* __PERF_ANNOTATE_H */
index 6d9c92c3d7cbb1958188205e20a7fe96b2c233fa..bac5ab6849675b9b22305a3d8902fb4e22f61c6e 100644 (file)
@@ -950,9 +950,9 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
        }
 }
 
-int hist_entry__inc_addr_samples(struct hist_entry *he, u64 ip)
+int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
 {
-       return symbol__inc_addr_samples(he->ms.sym, he->ms.map, ip);
+       return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
 }
 
 int hist_entry__annotate(struct hist_entry *he, struct list_head *head,
index 8a201f755534ba54633526b56dadc27adf311da5..2c6cdae6a764634846a7ed0c29d562e77a346fa1 100644 (file)
@@ -77,7 +77,7 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
 size_t hists__fprintf(struct hists *self, struct hists *pair,
                      bool show_displacement, FILE *fp);
 
-int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip);
+int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
 int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
                         size_t privsize);
 
@@ -91,18 +91,20 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
 #ifdef NO_NEWT_SUPPORT
 static inline int hists__browse(struct hists *self __used,
                                const char *helpline __used,
-                               const char *ev_name __used)
+                               const char *ev_name __used, int evidx __used)
 {
        return 0;
 }
 
 static inline int hists__tui_browse_tree(struct rb_root *self __used,
-                                        const char *help __used)
+                                        const char *help __used,
+                                        int evidx __used)
 {
        return 0;
 }
 
-static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
+static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
+                                          int evidx __used)
 {
        return 0;
 }
@@ -111,13 +113,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
 #else
 #include <newt.h>
 int hists__browse(struct hists *self, const char *helpline,
-                 const char *ev_name);
-int hist_entry__tui_annotate(struct hist_entry *self);
+                 const char *ev_name, int evidx);
+int hist_entry__tui_annotate(struct hist_entry *self, int evidx);
 
 #define KEY_LEFT NEWT_KEY_LEFT
 #define KEY_RIGHT NEWT_KEY_RIGHT
 
-int hists__tui_browse_tree(struct rb_root *self, const char *help);
+int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx);
 #endif
 
 unsigned int hists__sort_list_width(struct hists *self);
index daa7138d80156e6b3ed464d55c929d5fe63a0998..8d8a16895af7a48c3dcf714f3c70ded8e0195317 100644 (file)
@@ -61,7 +61,7 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
 
 static double objdump_line__calc_percent(struct objdump_line *self,
                                         struct list_head *head,
-                                        struct symbol *sym)
+                                        struct symbol *sym, int evidx)
 {
        double percent = 0.0;
 
@@ -70,7 +70,7 @@ static double objdump_line__calc_percent(struct objdump_line *self,
                unsigned int hits = 0;
                struct annotation *notes = symbol__annotation(sym);
                struct source_line *src_line = notes->src_line;
-               struct sym_hist *h = notes->histogram;
+               struct sym_hist *h = annotation__histogram(notes, evidx);
                s64 offset = self->offset;
                struct objdump_line *next = objdump__get_next_ip_line(head, self);
 
@@ -183,12 +183,12 @@ out:
        return key;
 }
 
-int hist_entry__tui_annotate(struct hist_entry *he)
+int hist_entry__tui_annotate(struct hist_entry *he, int evidx)
 {
-       return symbol__tui_annotate(he->ms.sym, he->ms.map);
+       return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx);
 }
 
-int symbol__tui_annotate(struct symbol *sym, struct map *map)
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
 {
        struct objdump_line *pos, *n;
        struct objdump_line_rb_node *rbpos;
@@ -223,7 +223,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map)
                        browser.b.width = line_len;
                rbpos = objdump_line__rb(pos);
                rbpos->idx = browser.b.nr_entries++;
-               rbpos->percent = objdump_line__calc_percent(pos, &head, sym);
+               rbpos->percent = objdump_line__calc_percent(pos, &head, sym, evidx);
                if (rbpos->percent < 0.01)
                        continue;
                objdump__insert_line(&browser.entries, rbpos);
index 86428239fa6574c4361d7c9beb8a3b51c9ba4e3e..294b49538522b7dedb7bd037ad9a95ae9cf6555d 100644 (file)
@@ -797,7 +797,8 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
        return printed;
 }
 
-int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
+int hists__browse(struct hists *self, const char *helpline,
+                 const char *ev_name, int evidx)
 {
        struct hist_browser *browser = hist_browser__new(self);
        struct pstack *fstack;
@@ -935,7 +936,7 @@ do_annotate:
                        if (he == NULL)
                                continue;
 
-                       hist_entry__tui_annotate(he);
+                       hist_entry__tui_annotate(he, evidx);
                } else if (choice == browse_map)
                        map__browse(browser->selection->map);
                else if (choice == zoom_dso) {
@@ -984,7 +985,7 @@ out:
        return key;
 }
 
-int hists__tui_browse_tree(struct rb_root *self, const char *help)
+int hists__tui_browse_tree(struct rb_root *self, const char *help, int evidx)
 {
        struct rb_node *first = rb_first(self), *nd = first, *next;
        int key = 0;
@@ -993,7 +994,7 @@ int hists__tui_browse_tree(struct rb_root *self, const char *help)
                struct hists *hists = rb_entry(nd, struct hists, rb_node);
                const char *ev_name = __event_name(hists->type, hists->config);
 
-               key = hists__browse(hists, help, ev_name);
+               key = hists__browse(hists, help, ev_name, evidx);
                switch (key) {
                case NEWT_KEY_TAB:
                        next = rb_next(nd);