]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf hist: Add struct he_mem_stat
authorNamhyung Kim <namhyung@kernel.org>
Wed, 30 Apr 2025 20:55:41 +0000 (13:55 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 2 May 2025 18:36:14 +0000 (15:36 -0300)
The 'struct he_mem_stat' is to save detailed information about memory
instruction.  It'll be used to show breakdown of various data from
PERF_SAMPLE_DATA_SRC.  Note that this structure is generic and the
contents will be different depending on actual data it'll use later.

The information about the actual data will be saved in 'struct hists'
and its length is in nr_mem_stats.  This commit just adds ground works
and does nothing since hists->nr_mem_stats is 0 for now.

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: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Link: https://lore.kernel.org/r/20250430205548.789750-5-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/hist.c
tools/perf/util/hist.h

index d65228c1141251fb2e70fb95a4e49be18debc4ca..fcb9f0db0c92a229db315473fc597bc9efd8ce37 100644 (file)
@@ -336,6 +336,67 @@ static void he_stat__decay(struct he_stat *he_stat)
        he_stat->latency = (he_stat->latency * 7) / 8;
 }
 
+static int hists__update_mem_stat(struct hists *hists, struct hist_entry *he,
+                                 struct mem_info *mi, u64 period)
+{
+       if (hists->nr_mem_stats == 0)
+               return 0;
+
+       if (he->mem_stat == NULL) {
+               he->mem_stat = calloc(hists->nr_mem_stats, sizeof(*he->mem_stat));
+               if (he->mem_stat == NULL)
+                       return -1;
+       }
+
+       for (int i = 0; i < hists->nr_mem_stats; i++) {
+               int idx = 0; /* TODO: get correct index from mem info */
+
+               (void)mi;
+               he->mem_stat[i].entries[idx] += period;
+       }
+       return 0;
+}
+
+static void hists__add_mem_stat(struct hists *hists, struct hist_entry *dst,
+                               struct hist_entry *src)
+{
+       if (hists->nr_mem_stats == 0)
+               return;
+
+       for (int i = 0; i < hists->nr_mem_stats; i++) {
+               for (int k = 0; k < MEM_STAT_LEN; k++)
+                       dst->mem_stat[i].entries[k] += src->mem_stat[i].entries[k];
+       }
+}
+
+static int hists__clone_mem_stat(struct hists *hists, struct hist_entry *dst,
+                                 struct hist_entry *src)
+{
+       if (hists->nr_mem_stats == 0)
+               return 0;
+
+       dst->mem_stat = calloc(hists->nr_mem_stats, sizeof(*dst->mem_stat));
+       if (dst->mem_stat == NULL)
+               return -1;
+
+       for (int i = 0; i < hists->nr_mem_stats; i++) {
+               for (int k = 0; k < MEM_STAT_LEN; k++)
+                       dst->mem_stat[i].entries[k] = src->mem_stat[i].entries[k];
+       }
+       return 0;
+}
+
+static void hists__decay_mem_stat(struct hists *hists, struct hist_entry *he)
+{
+       if (hists->nr_mem_stats == 0)
+               return;
+
+       for (int i = 0; i < hists->nr_mem_stats; i++) {
+               for (int k = 0; k < MEM_STAT_LEN; k++)
+                       he->mem_stat[i].entries[k] = (he->mem_stat[i].entries[k] * 7) / 8;
+       }
+}
+
 static void hists__delete_entry(struct hists *hists, struct hist_entry *he);
 
 static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
@@ -350,6 +411,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
        if (symbol_conf.cumulate_callchain)
                he_stat__decay(he->stat_acc);
        decay_callchain(he->callchain);
+       hists__decay_mem_stat(hists, he);
 
        if (!he->depth) {
                u64 period_diff = prev_period - he->stat.period;
@@ -693,6 +755,10 @@ out:
                he_stat__add_cpumode_period(&he->stat, al->cpumode, period);
        if (symbol_conf.cumulate_callchain)
                he_stat__add_cpumode_period(he->stat_acc, al->cpumode, period);
+       if (hists__update_mem_stat(hists, he, entry->mem_info, period) < 0) {
+               hist_entry__delete(he);
+               return NULL;
+       }
        return he;
 }
 
@@ -1423,6 +1489,7 @@ void hist_entry__delete(struct hist_entry *he)
        free_callchain(he->callchain);
        zfree(&he->trace_output);
        zfree(&he->raw_data);
+       zfree(&he->mem_stat);
        ops->free(he);
 }
 
@@ -1572,6 +1639,7 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
                cmp = hist_entry__collapse_hierarchy(hpp_list, iter, he);
                if (!cmp) {
                        he_stat__add_stat(&iter->stat, &he->stat);
+                       hists__add_mem_stat(hists, iter, he);
                        return iter;
                }
 
@@ -1613,6 +1681,11 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
                        new->srcfile = NULL;
        }
 
+       if (hists__clone_mem_stat(hists, new, he) < 0) {
+               hist_entry__delete(new);
+               return NULL;
+       }
+
        rb_link_node(&new->rb_node_in, parent, p);
        rb_insert_color_cached(&new->rb_node_in, root, leftmost);
        return new;
@@ -1695,6 +1768,7 @@ static int hists__collapse_insert_entry(struct hists *hists,
                        he_stat__add_stat(&iter->stat, &he->stat);
                        if (symbol_conf.cumulate_callchain)
                                he_stat__add_stat(iter->stat_acc, he->stat_acc);
+                       hists__add_mem_stat(hists, iter, he);
 
                        if (hist_entry__has_callchains(he) && symbol_conf.use_callchain) {
                                struct callchain_cursor *cursor = get_tls_callchain_cursor();
index 76efd8952507a5610ad221085eef23fa0e1eaede..aba1d84ca074f27b83aeeb4de5f2d71f7386f91c 100644 (file)
@@ -100,6 +100,13 @@ enum hist_column {
 struct thread;
 struct dso;
 
+#define MEM_STAT_LEN  8
+
+struct he_mem_stat {
+       /* meaning of entries depends on enum mem_stat_type */
+       u64                     entries[MEM_STAT_LEN];
+};
+
 struct hists {
        struct rb_root_cached   entries_in_array[2];
        struct rb_root_cached   *entries_in;
@@ -125,6 +132,7 @@ struct hists {
        struct perf_hpp_list    *hpp_list;
        struct list_head        hpp_formats;
        int                     nr_hpp_node;
+       int                     nr_mem_stats;
 };
 
 #define hists__has(__h, __f) (__h)->hpp_list->__f
@@ -232,6 +240,7 @@ struct hist_entry {
        } pairs;
        struct he_stat          stat;
        struct he_stat          *stat_acc;
+       struct he_mem_stat      *mem_stat;
        struct map_symbol       ms;
        struct thread           *thread;
        struct comm             *comm;