mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
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>
This commit is contained in:
parent
930d4c45c6
commit
9fcb43e27c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user