Commit 6e19839a authored by Ian Rogers's avatar Ian Rogers Committed by Namhyung Kim
Browse files

perf sort: Use perf_env to set arch sort keys and header



Previously arch_support_sort_key and arch_perf_header_entry used a
weak symbol to compile as appropriate for x86 and powerpc. A
limitation to this is that the handling of a data file could vary in
cross-platform development. Change to using the perf_env of the
current session to determine the architecture kind and set the sort
key and header entries as appropriate.

Signed-off-by: default avatarIan Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250724163302.596743-23-irogers@google.com


Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent a563c9f3
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@ perf-util-y += mem-events.o
perf-util-y += pmu.o
perf-util-y += sym-handling.o
perf-util-y += evsel.o
perf-util-y += event.o

perf-util-$(CONFIG_LIBDW) += skip-callchain-idx.o

+0 −34
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <linux/types.h>
#include <linux/string.h>
#include <linux/zalloc.h>

#include "../../../util/event.h"
#include "../../../util/synthetic-events.h"
#include "../../../util/machine.h"
#include "../../../util/tool.h"
#include "../../../util/map.h"
#include "../../../util/debug.h"
#include "../../../util/sample.h"

const char *arch_perf_header_entry(const char *se_header)
{
	if (!strcmp(se_header, "Local INSTR Latency"))
		return "Finish Cyc";
	else if (!strcmp(se_header, "INSTR Latency"))
		return "Global Finish_cyc";
	else if (!strcmp(se_header, "Local Pipeline Stage Cycle"))
		return "Dispatch Cyc";
	else if (!strcmp(se_header, "Pipeline Stage Cycle"))
		return "Global Dispatch_cyc";
	return se_header;
}

int arch_support_sort_key(const char *sort_key)
{
	if (!strcmp(sort_key, "p_stage_cyc"))
		return 1;
	if (!strcmp(sort_key, "local_p_stage_cyc"))
		return 1;
	return 0;
}
+0 −19
Original line number Diff line number Diff line
@@ -91,22 +91,3 @@ int perf_event__synthesize_extra_kmaps(const struct perf_tool *tool,
}

#endif

const char *arch_perf_header_entry(const char *se_header)
{
	if (!strcmp(se_header, "Local Pipeline Stage Cycle"))
		return "Local Retire Latency";
	else if (!strcmp(se_header, "Pipeline Stage Cycle"))
		return "Retire Latency";

	return se_header;
}

int arch_support_sort_key(const char *sort_key)
{
	if (!strcmp(sort_key, "p_stage_cyc"))
		return 1;
	if (!strcmp(sort_key, "local_p_stage_cyc"))
		return 1;
	return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -947,7 +947,7 @@ int cmd_annotate(int argc, const char **argv)
			annotate_opts.show_br_cntr = true;
	}

	if (setup_sorting(NULL) < 0)
	if (setup_sorting(/*evlist=*/NULL, perf_session__env(annotate.session)) < 0)
		usage_with_options(annotate_usage, options);

	ret = __cmd_annotate(&annotate);
+30 −23
Original line number Diff line number Diff line
@@ -195,12 +195,14 @@ static struct hist_entry_ops c2c_entry_ops = {

static int c2c_hists__init(struct c2c_hists *hists,
			   const char *sort,
			   int nr_header_lines);
			   int nr_header_lines,
			   struct perf_env *env);

static struct c2c_hists*
he__get_c2c_hists(struct hist_entry *he,
		  const char *sort,
		  int nr_header_lines)
		  int nr_header_lines,
		  struct perf_env *env)
{
	struct c2c_hist_entry *c2c_he;
	struct c2c_hists *hists;
@@ -214,7 +216,7 @@ he__get_c2c_hists(struct hist_entry *he,
	if (!hists)
		return NULL;

	ret = c2c_hists__init(hists, sort, nr_header_lines);
	ret = c2c_hists__init(hists, sort, nr_header_lines, env);
	if (ret) {
		free(hists);
		return NULL;
@@ -350,7 +352,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,

		mi = mi_dup;

		c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
		c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2, machine->env);
		if (!c2c_hists)
			goto free_mi;

@@ -1966,7 +1968,8 @@ static struct c2c_fmt *get_format(const char *name)
	return c2c_fmt;
}

static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name)
static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name,
				  struct perf_env *env __maybe_unused)
{
	struct c2c_fmt *c2c_fmt = get_format(name);
	int level = 0;
@@ -1980,14 +1983,14 @@ static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name)
	return 0;
}

static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)
static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name, struct perf_env *env)
{
	struct c2c_fmt *c2c_fmt = get_format(name);
	struct c2c_dimension *dim;

	if (!c2c_fmt) {
		reset_dimensions();
		return sort_dimension__add(hpp_list, name, NULL, 0);
		return sort_dimension__add(hpp_list, name, /*evlist=*/NULL, env, /*level=*/0);
	}

	dim = c2c_fmt->dim;
@@ -2008,7 +2011,7 @@ static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)
										\
		for (tok = strtok_r((char *)_list, ", ", &tmp);			\
				tok; tok = strtok_r(NULL, ", ", &tmp)) {	\
			ret = _fn(hpp_list, tok);				\
			ret = _fn(hpp_list, tok, env);				\
			if (ret == -EINVAL) {					\
				pr_err("Invalid --fields key: `%s'", tok);	\
				break;						\
@@ -2021,7 +2024,8 @@ static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)

static int hpp_list__parse(struct perf_hpp_list *hpp_list,
			   const char *output_,
			   const char *sort_)
			   const char *sort_,
			   struct perf_env *env)
{
	char *output = output_ ? strdup(output_) : NULL;
	char *sort   = sort_   ? strdup(sort_) : NULL;
@@ -2052,7 +2056,8 @@ static int hpp_list__parse(struct perf_hpp_list *hpp_list,

static int c2c_hists__init(struct c2c_hists *hists,
			   const char *sort,
			   int nr_header_lines)
			   int nr_header_lines,
			   struct perf_env *env)
{
	__hists__init(&hists->hists, &hists->list);

@@ -2066,15 +2071,16 @@ static int c2c_hists__init(struct c2c_hists *hists,
	/* Overload number of header lines.*/
	hists->list.nr_header_lines = nr_header_lines;

	return hpp_list__parse(&hists->list, NULL, sort);
	return hpp_list__parse(&hists->list, /*output=*/NULL, sort, env);
}

static int c2c_hists__reinit(struct c2c_hists *c2c_hists,
			     const char *output,
			     const char *sort)
			     const char *sort,
			     struct perf_env *env)
{
	perf_hpp__reset_output_field(&c2c_hists->list);
	return hpp_list__parse(&c2c_hists->list, output, sort);
	return hpp_list__parse(&c2c_hists->list, output, sort, env);
}

#define DISPLAY_LINE_LIMIT  0.001
@@ -2207,8 +2213,9 @@ static int filter_cb(struct hist_entry *he, void *arg __maybe_unused)
	return 0;
}

static int resort_cl_cb(struct hist_entry *he, void *arg __maybe_unused)
static int resort_cl_cb(struct hist_entry *he, void *arg)
{
	struct perf_env *env = arg;
	struct c2c_hist_entry *c2c_he;
	struct c2c_hists *c2c_hists;
	bool display = he__display(he, &c2c.shared_clines_stats);
@@ -2222,7 +2229,7 @@ static int resort_cl_cb(struct hist_entry *he, void *arg __maybe_unused)
		c2c_he->cacheline_idx = idx++;
		calc_width(c2c_he);

		c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
		c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort, env);

		hists__collapse_resort(&c2c_hists->hists, NULL);
		hists__output_resort_cb(&c2c_hists->hists, NULL, filter_cb);
@@ -2334,7 +2341,7 @@ static int resort_shared_cl_cb(struct hist_entry *he, void *arg __maybe_unused)
	return 0;
}

static int hists__iterate_cb(struct hists *hists, hists__resort_cb_t cb)
static int hists__iterate_cb(struct hists *hists, hists__resort_cb_t cb, void *arg)
{
	struct rb_node *next = rb_first_cached(&hists->entries);
	int ret = 0;
@@ -2343,7 +2350,7 @@ static int hists__iterate_cb(struct hists *hists, hists__resort_cb_t cb)
		struct hist_entry *he;

		he = rb_entry(next, struct hist_entry, rb_node);
		ret = cb(he, NULL);
		ret = cb(he, arg);
		if (ret)
			break;
		next = rb_next(&he->rb_node);
@@ -2449,7 +2456,7 @@ static void print_cacheline(struct c2c_hists *c2c_hists,
	hists__fprintf(&c2c_hists->hists, false, 0, 0, 0, out, false);
}

static void print_pareto(FILE *out)
static void print_pareto(FILE *out, struct perf_env *env)
{
	struct perf_hpp_list hpp_list;
	struct rb_node *nd;
@@ -2474,7 +2481,7 @@ static void print_pareto(FILE *out)
			    "dcacheline";

	perf_hpp_list__init(&hpp_list);
	ret = hpp_list__parse(&hpp_list, cl_output, NULL);
	ret = hpp_list__parse(&hpp_list, cl_output, /*evlist=*/NULL, env);

	if (WARN_ONCE(ret, "failed to setup sort entries\n"))
		return;
@@ -2539,7 +2546,7 @@ static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
	fprintf(out, "=================================================\n");
	fprintf(out, "#\n");

	print_pareto(out);
	print_pareto(out, perf_session__env(session));
}

#ifdef HAVE_SLANG_SUPPORT
@@ -3097,7 +3104,7 @@ static int perf_c2c__report(int argc, const char **argv)
		goto out_session;
	}

	err = c2c_hists__init(&c2c.hists, "dcacheline", 2);
	err = c2c_hists__init(&c2c.hists, "dcacheline", 2, perf_session__env(session));
	if (err) {
		pr_debug("Failed to initialize hists\n");
		goto out_session;
@@ -3181,13 +3188,13 @@ static int perf_c2c__report(int argc, const char **argv)
	else if (c2c.display == DISPLAY_SNP_PEER)
		sort_str = "tot_peer";

	c2c_hists__reinit(&c2c.hists, output_str, sort_str);
	c2c_hists__reinit(&c2c.hists, output_str, sort_str, perf_session__env(session));

	ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting...");

	hists__collapse_resort(&c2c.hists.hists, NULL);
	hists__output_resort_cb(&c2c.hists.hists, &prog, resort_shared_cl_cb);
	hists__iterate_cb(&c2c.hists.hists, resort_cl_cb);
	hists__iterate_cb(&c2c.hists.hists, resort_cl_cb, perf_session__env(session));

	ui_progress__finish();

Loading