diff options
author | Namhyung Kim <namhyung@kernel.org> | 2025-04-30 23:55:42 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2025-05-02 21:36:14 +0300 |
commit | 9fcb43e27c0e2696f6315022972e75ec0da8eb86 (patch) | |
tree | a42f4fdabfc84c4d022a48128aca3fc4697ea16e | |
parent | 930d4c45c687246d02950d4aa2608641f26498ec (diff) | |
download | linux-9fcb43e27c0e2696f6315022972e75ec0da8eb86.tar.xz |
perf hist: Basic support for mem_stat accounting
Add a logic to account he->mem_stat based on mem_stat_type in hists.
Each mem_stat entry will have different meaning based on the type so the
index in the array is calculated at runtime using the corresponding
value in the sample.data_src.
Still hists has no mem_stat_types yet so this code won't work for now.
Later hists->mem_stat_types will be allocated based on what users want
in the output actually.
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-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/ui/hist.c | 39 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 6 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 4 | ||||
-rw-r--r-- | tools/perf/util/mem-events.c | 18 | ||||
-rw-r--r-- | tools/perf/util/mem-events.h | 6 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 4 |
6 files changed, 75 insertions, 2 deletions
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index ec44633207aa..2aad46bbd2ed 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -11,6 +11,7 @@ #include "../util/sort.h" #include "../util/evsel.h" #include "../util/evlist.h" +#include "../util/mem-events.h" #include "../util/thread.h" #include "../util/util.h" @@ -500,6 +501,12 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, return 0; } +static bool perf_hpp__is_mem_stat_entry(struct perf_hpp_fmt *fmt) +{ + (void)fmt; + return false; +} + static bool perf_hpp__is_hpp_entry(struct perf_hpp_fmt *a) { return a->header == hpp__header_fn; @@ -1022,3 +1029,35 @@ int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, return 0; } + +int perf_hpp__alloc_mem_stats(struct perf_hpp_list *list, struct evlist *evlist) +{ + struct perf_hpp_fmt *fmt; + struct evsel *evsel; + enum mem_stat_type mst[16]; + unsigned nr_mem_stats = 0; + + perf_hpp_list__for_each_format(list, fmt) { + if (!perf_hpp__is_mem_stat_entry(fmt)) + continue; + + assert(nr_mem_stats < ARRAY_SIZE(mst)); + mst[nr_mem_stats++] = PERF_MEM_STAT_UNKNOWN; + } + + if (nr_mem_stats == 0) + return 0; + + evlist__for_each_entry(evlist, evsel) { + struct hists *hists = evsel__hists(evsel); + + hists->mem_stat_types = calloc(nr_mem_stats, + sizeof(*hists->mem_stat_types)); + if (hists->mem_stat_types == NULL) + return -ENOMEM; + + memcpy(hists->mem_stat_types, mst, nr_mem_stats * sizeof(*mst)); + hists->nr_mem_stats = nr_mem_stats; + } + return 0; +} diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index fcb9f0db0c92..7759c1818c1a 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -349,9 +349,10 @@ static int hists__update_mem_stat(struct hists *hists, struct hist_entry *he, } for (int i = 0; i < hists->nr_mem_stats; i++) { - int idx = 0; /* TODO: get correct index from mem info */ + int idx = mem_stat_index(hists->mem_stat_types[i], + mem_info__const_data_src(mi)->val); - (void)mi; + assert(0 <= idx && idx < MEM_STAT_LEN); he->mem_stat[i].entries[idx] += period; } return 0; @@ -3052,6 +3053,7 @@ static void hists_evsel__exit(struct evsel *evsel) struct perf_hpp_list_node *node, *tmp; hists__delete_all_entries(hists); + zfree(&hists->mem_stat_types); list_for_each_entry_safe(node, tmp, &hists->hpp_formats, list) { perf_hpp_list__for_each_format_safe(&node->hpp, fmt, pos) { diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index aba1d84ca074..509af09691b8 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -9,6 +9,7 @@ #include "events_stats.h" #include "evsel.h" #include "map_symbol.h" +#include "mem-events.h" #include "mutex.h" #include "sample.h" #include "spark.h" @@ -133,6 +134,7 @@ struct hists { struct list_head hpp_formats; int nr_hpp_node; int nr_mem_stats; + enum mem_stat_type *mem_stat_types; }; #define hists__has(__h, __f) (__h)->hpp_list->__f @@ -597,6 +599,8 @@ void perf_hpp__reset_output_field(struct perf_hpp_list *list); void perf_hpp__append_sort_keys(struct perf_hpp_list *list); int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, struct evlist *evlist); +int perf_hpp__alloc_mem_stats(struct perf_hpp_list *list, + struct evlist *evlist); bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index 884d9aebce91..1bc60ad3dc31 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c @@ -799,3 +799,21 @@ void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add) stats->nomap += add->nomap; stats->noparse += add->noparse; } + +/* + * It returns an index in hist_entry->mem_stat array for the given val which + * represents a data-src based on the mem_stat_type. + * + * For example, when mst is about cache level, the index can be 1 for L1, 2 for + * L2 and so on. + */ +int mem_stat_index(const enum mem_stat_type mst, const u64 val) +{ + switch (mst) { + case PERF_MEM_STAT_UNKNOWN: /* placeholder */ + default: + break; + } + (void)val; + return -1; +} diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h index a5c19d39ee37..2604464f9858 100644 --- a/tools/perf/util/mem-events.h +++ b/tools/perf/util/mem-events.h @@ -89,4 +89,10 @@ struct hist_entry; int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi); void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add); +enum mem_stat_type { + PERF_MEM_STAT_UNKNOWN, /* placeholder */ +}; + +int mem_stat_index(const enum mem_stat_type mst, const u64 data_src); + #endif /* __PERF_MEM_EVENTS_H */ diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index ae8b8ceb82f3..6024f588f66f 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -4163,6 +4163,10 @@ int setup_sorting(struct evlist *evlist) if (err < 0) return err; + err = perf_hpp__alloc_mem_stats(&perf_hpp_list, evlist); + if (err < 0) + return err; + /* copy sort keys to output fields */ perf_hpp__setup_output_field(&perf_hpp_list); /* and then copy output fields to sort keys */ |