Commit 930d4c45 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo
Browse files

perf hist: Add struct he_mem_stat



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: 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-5-namhyung@kernel.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 29e6392e
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
@@ -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 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
		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();
+9 −0
Original line number Diff line number Diff line
@@ -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;