Commit 9fcb43e2 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarNamhyung 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 930d4c45
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -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;
}
+4 −2
Original line number Diff line number Diff line
@@ -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) {
+4 −0
Original line number Diff line number Diff line
@@ -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);
+18 −0
Original line number Diff line number Diff line
@@ -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;
}
+6 −0
Original line number Diff line number Diff line
@@ -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 */
Loading