]> git.itanic.dy.fi Git - linux-stable/commitdiff
perf annotate: Split branch stack cycles information out of 'struct annotation_line'
authorNamhyung Kim <namhyung@kernel.org>
Fri, 3 Nov 2023 19:19:03 +0000 (12:19 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 9 Nov 2023 16:49:33 +0000 (13:49 -0300)
The cycles info is used only when branch stack is provided.  Separate
them from 'struct annotation_line' into a separate struct and lazy
allocate them to save some memory.

Committer notes:

Make annotation__compute_ipc() check if the lazy allocation works,
bailing out if so, its callers already do error checking and
propagation.

Signed-off-by: Namhyung 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-2-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/ui/browsers/annotate.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h

index ccdb2cd11fbf0325f1e2bcfa35fa86d5986b3261..d2470f87344d0edb4cc0f86ca14b69683ffeaf87 100644 (file)
@@ -337,7 +337,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
                                max_percent = percent;
                }
 
-               if (max_percent < 0.01 && pos->al.ipc == 0) {
+               if (max_percent < 0.01 && (!pos->al.cycles || pos->al.cycles->ipc == 0)) {
                        RB_CLEAR_NODE(&pos->al.rb_node);
                        continue;
                }
index 82956adf99632d742f777f01d4177ce575ddfbd6..99ff3bb9cad8daa688acd658aca0383798cca917 100644 (file)
@@ -1100,8 +1100,8 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64
                for (offset = start; offset <= end; offset++) {
                        struct annotation_line *al = notes->offsets[offset];
 
-                       if (al && al->ipc == 0.0) {
-                               al->ipc = ipc;
+                       if (al && al->cycles && al->cycles->ipc == 0.0) {
+                               al->cycles->ipc = ipc;
                                cover_insn++;
                        }
                }
@@ -1114,12 +1114,13 @@ static void annotation__count_and_fill(struct annotation *notes, u64 start, u64
        }
 }
 
-void annotation__compute_ipc(struct annotation *notes, size_t size)
+static int annotation__compute_ipc(struct annotation *notes, size_t size)
 {
+       int err = 0;
        s64 offset;
 
        if (!notes->src || !notes->src->cycles_hist)
-               return;
+               return 0;
 
        notes->total_insn = annotation__count_insn(notes, 0, size - 1);
        notes->hit_cycles = 0;
@@ -1134,18 +1135,39 @@ void annotation__compute_ipc(struct annotation *notes, size_t size)
                if (ch && ch->cycles) {
                        struct annotation_line *al;
 
+                       al = notes->offsets[offset];
+                       if (al && al->cycles == NULL) {
+                               al->cycles = zalloc(sizeof(*al->cycles));
+                               if (al->cycles == NULL) {
+                                       err = ENOMEM;
+                                       break;
+                               }
+                       }
                        if (ch->have_start)
                                annotation__count_and_fill(notes, ch->start, offset, ch);
-                       al = notes->offsets[offset];
                        if (al && ch->num_aggr) {
-                               al->cycles = ch->cycles_aggr / ch->num_aggr;
-                               al->cycles_max = ch->cycles_max;
-                               al->cycles_min = ch->cycles_min;
+                               al->cycles->avg = ch->cycles_aggr / ch->num_aggr;
+                               al->cycles->max = ch->cycles_max;
+                               al->cycles->min = ch->cycles_min;
                        }
                        notes->have_cycles = true;
                }
        }
+
+       if (err) {
+               while (++offset < (s64)size) {
+                       struct cyc_hist *ch = &notes->src->cycles_hist[offset];
+
+                       if (ch && ch->cycles) {
+                               struct annotation_line *al = notes->offsets[offset];
+                               if (al)
+                                       zfree(&al->cycles);
+                       }
+               }
+       }
+
        annotation__unlock(notes);
+       return 0;
 }
 
 int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
@@ -1225,6 +1247,7 @@ static void annotation_line__exit(struct annotation_line *al)
 {
        zfree_srcline(&al->path);
        zfree(&al->line);
+       zfree(&al->cycles);
 }
 
 static size_t disasm_line_size(int nr)
@@ -3083,8 +3106,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
        int printed;
 
        if (first_line && (al->offset == -1 || percent_max == 0.0)) {
-               if (notes->have_cycles) {
-                       if (al->ipc == 0.0 && al->cycles == 0)
+               if (notes->have_cycles && al->cycles) {
+                       if (al->cycles->ipc == 0.0 && al->cycles->avg == 0)
                                show_title = true;
                } else
                        show_title = true;
@@ -3121,17 +3144,17 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
        }
 
        if (notes->have_cycles) {
-               if (al->ipc)
-                       obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
+               if (al->cycles && al->cycles->ipc)
+                       obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->cycles->ipc);
                else if (!show_title)
                        obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
                else
                        obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
 
                if (!notes->options->show_minmax_cycle) {
-                       if (al->cycles)
+                       if (al->cycles && al->cycles->avg)
                                obj__printf(obj, "%*" PRIu64 " ",
-                                          ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
+                                          ANNOTATION__CYCLES_WIDTH - 1, al->cycles->avg);
                        else if (!show_title)
                                obj__printf(obj, "%*s",
                                            ANNOTATION__CYCLES_WIDTH, " ");
@@ -3145,8 +3168,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
 
                                scnprintf(str, sizeof(str),
                                        "%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
-                                       al->cycles, al->cycles_min,
-                                       al->cycles_max);
+                                       al->cycles->avg, al->cycles->min,
+                                       al->cycles->max);
 
                                obj__printf(obj, "%*s ",
                                            ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
@@ -3264,7 +3287,11 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
 
        annotation__set_offsets(notes, size);
        annotation__mark_jump_targets(notes, sym);
-       annotation__compute_ipc(notes, size);
+
+       err = annotation__compute_ipc(notes, size);
+       if (err)
+               goto out_free_offsets;
+
        annotation__init_column_widths(notes, sym);
        notes->nr_events = nr_pcnt;
 
index 96278055917601c31ee928099188ddd35d5c1e0c..19bc2f03917575a87483d4e114f46155c75353fe 100644 (file)
@@ -130,6 +130,13 @@ struct annotation_data {
        struct sym_hist_entry    he;
 };
 
+struct cycles_info {
+       float                    ipc;
+       u64                      avg;
+       u64                      max;
+       u64                      min;
+};
+
 struct annotation_line {
        struct list_head         node;
        struct rb_node           rb_node;
@@ -137,12 +144,9 @@ struct annotation_line {
        char                    *line;
        int                      line_nr;
        char                    *fileloc;
-       int                      jump_sources;
-       float                    ipc;
-       u64                      cycles;
-       u64                      cycles_max;
-       u64                      cycles_min;
        char                    *path;
+       struct cycles_info      *cycles;
+       int                      jump_sources;
        u32                      idx;
        int                      idx_asm;
        int                      data_nr;
@@ -325,7 +329,6 @@ static inline bool annotation_line__filter(struct annotation_line *al, struct an
 }
 
 void annotation__set_offsets(struct annotation *notes, s64 size);
-void annotation__compute_ipc(struct annotation *notes, size_t size);
 void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym);
 void annotation__update_column_widths(struct annotation *notes);
 void annotation__init_column_widths(struct annotation *notes, struct symbol *sym);