mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: John Garry <john.g.garry@oracle.com>
To: acme@kernel.org, irogers@google.com, namhyung@kernel.org,
	jolsa@kernel.org
Cc: linux-arm-kernel@lists.infradead.org,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
	renyu.zj@linux.alibaba.com, shangxiaojing@huawei.com,
	zhangshaokun@hisilicon.com, qiangqing.zhang@nxp.com,
	kjain@linux.ibm.com, kan.liang@linux.intel.com,
	John Garry <john.g.garry@oracle.com>
Subject: [PATCH RFC 6/9] perf metrics: Add metricgroup_sys_metric_supported()
Date: Wed, 28 Jun 2023 10:29:46 +0000	[thread overview]
Message-ID: <20230628102949.2598096-7-john.g.garry@oracle.com> (raw)
In-Reply-To: <20230628102949.2598096-1-john.g.garry@oracle.com>

Add a function to match a sys metric for the host.

Currently we do the following the match a metric:
- iter through all sys metrics for all sys event tables
- for each iter, iter through all PMUs
- if the PMU Unit and id match the metric Unit and compat, then the metric
  matches for the host

We should not be required to match a metric Unit and compat, unless the
metric explicitly specifies target PMU, like:
 "MetricExpr": "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@",

Rather, we should be match against events aliases present from the events
in the same pmu_sys_events structure. Those events added will be gated on
matching Unit and Compat specifiers.

The steps in metricgroup_match_sys_pm() are as follows:
a. Find event table associated with metric table
b. Call add_metric() for the metric, which resolves referenced metrics and
   generates a list of type struct metric
c. Iter through metric list and parse ids, to find a list of evsel's
d. For each evsel, match event against known events in event table
e. If we can't match an evsel as the metric explicitly specifies target PMU,
   just match evsel PMU against metric Unit and Compat.

Step d. is required as in parse_ids() -> parse_events_add_pmu(), we might
have matched metric for other system which has the same name, i.e. when
we find matching event and PMU, we must ensure it matches compat for event
from metric's associated event table.

Function metricgroup__sys_event_iter() will now call
metricgroup_sys_metric_supported() to match the metric.

Signed-off-by: John Garry <john.g.garry@oracle.com>
---
 tools/perf/util/metricgroup.c | 115 +++++++++++++++++++++++++++++++---
 1 file changed, 105 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
index 520436fbe99d..6be410363099 100644
--- a/tools/perf/util/metricgroup.c
+++ b/tools/perf/util/metricgroup.c
@@ -486,23 +486,18 @@ struct metricgroup_iter_data {
 	void *data;
 };
 
+static bool metricgroup_sys_metric_supported(const struct pmu_metric *pm,
+			const struct pmu_metrics_table *table);
+
 static int metricgroup__sys_event_iter(const struct pmu_metric *pm,
 				       const struct pmu_metrics_table *table,
 				       void *data)
 {
 	struct metricgroup_iter_data *d = data;
-	struct perf_pmu *pmu = NULL;
-
-	if (!pm->metric_expr || !pm->compat)
-		return 0;
-
-	while ((pmu = perf_pmus__scan(pmu))) {
-
-		if (!pmu->id || strcmp(pmu->id, pm->compat))
-			continue;
 
+	if (metricgroup_sys_metric_supported(pm, table))
 		return d->fn(pm, table, d->data);
-	}
+
 	return 0;
 }
 
@@ -1705,6 +1700,106 @@ static int parse_groups(struct evlist *perf_evlist,
 	return ret;
 }
 
+struct metricgroup__test_event {
+	struct pmu_event *found_event;
+	struct perf_pmu *pmu;
+	char *evsel_name;
+};
+
+static int metricgroup__test_event_iter(const struct pmu_event *pe,
+		const struct pmu_events_table *table __maybe_unused,
+		void *vdata)
+{
+	struct metricgroup__test_event *data = vdata;
+	struct pmu_event *found_event = data->found_event;
+	char *evsel_name = data->evsel_name;
+	struct perf_pmu *pmu = data->pmu;
+
+	if (strcasecmp(pe->name, evsel_name))
+		return 0;
+
+	if (!strcmp(pmu->id, pe->compat)) {
+		/* Copy, as pe is only valid in the iter */
+		memcpy(found_event, pe, sizeof(*pe));
+		/* Stop iter'ing */
+		return 1;
+	}
+
+	return 0;
+}
+
+static bool metricgroup_sys_metric_supported(const struct pmu_metric *pm,
+				const struct pmu_metrics_table *table)
+{
+	const struct pmu_events_table *events_table;
+	bool tool_events[PERF_TOOL_MAX] = {false};
+	struct metric *m = NULL;
+	bool ret = false;
+	int err;
+	LIST_HEAD(list);
+
+	events_table = sys_events_find_events_table(table);
+	if (!events_table)
+		return false;
+
+	err = add_metric(&list /* d->metric_list */, pm,
+			 NULL /* modifier */, false /* metric_no_group */,
+			 false /* metric_no_threshold */, false /* user_requested_cpu_list */,
+			 false /*system wide */, NULL /* root metric */,
+			 NULL /* visited */, table);
+	if (ret)
+		return false;
+
+	/*
+	 * We have a list of metrics. Now generate an evlist per metric, and
+	 * match each evsel. We match evsel by findings its corresponding PMU
+	 * and then ensuring the we can find it in either a. the event list
+	 * associated with the metric or b. if it is a metric referencing an
+	 * explicit PMU. In both cases we match the pmu->id against the event
+	 * compat.
+	 */
+	list_for_each_entry(m, &list, nd) {
+		struct evsel *evsel;
+
+		err = parse_ids(false, NULL, m->pctx, m->modifier,
+				m->group_events, tool_events, &m->evlist);
+		if (err)
+			return false;
+
+		evlist__for_each_entry(m->evlist, evsel) {
+			struct perf_pmu *pmu = perf_pmus__find(evsel->pmu_name);
+			struct pmu_event found_event = {};
+			struct metricgroup__test_event data = {
+				.evsel_name = evsel->name,
+				.found_event = &found_event,
+				.pmu = pmu,
+			};
+
+			if (!pmu)
+				return false;
+
+			pmu_events_table_for_each_event(events_table,
+					metricgroup__test_event_iter,
+					&data);
+			if (found_event.name)
+				continue;
+
+			/*
+			 * We dould not find alias event, so maybe our evsel
+			 * is for a specific PMU.
+			 */
+			if (strchr(evsel->name, '/')) {
+				if (pmu_event_match_pmu(pm->pmu, pm->compat, pmu))
+					continue;
+			}
+
+			return false;
+		}
+	}
+
+	return true;
+}
+
 int metricgroup__parse_groups(struct evlist *perf_evlist,
 			      const char *pmu,
 			      const char *str,
-- 
2.35.3


  parent reply	other threads:[~2023-06-28 10:34 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-28 10:29 [PATCH RFC 0/9] perf tool: sys event metric support re-write John Garry
2023-06-28 10:29 ` [PATCH RFC 1/9] perf metrics: Delete metricgroup_add_iter_data.table John Garry
2023-06-30 17:22   ` Ian Rogers
2023-06-28 10:29 ` [PATCH RFC 2/9] perf metrics: Don't iter sys metrics if we already found a CPU match John Garry
2023-06-30 17:41   ` Ian Rogers
2023-07-03 13:09     ` John Garry
2023-07-12  5:40       ` Ian Rogers
2023-07-12  9:37         ` John Garry
2023-06-28 10:29 ` [PATCH RFC 3/9] perf metrics: Pass cpu and sys tables to metricgroup__add_metric() John Garry
2023-06-30 18:39   ` Ian Rogers
2023-07-03 15:20     ` John Garry
2023-06-28 10:29 ` [PATCH RFC 4/9] perf jevents: Add sys_events_find_events_table() John Garry
2023-06-30 19:00   ` Ian Rogers
2023-06-30 20:16     ` Ian Rogers
2023-07-03 15:15       ` John Garry
2023-07-12  6:05         ` Ian Rogers
2023-07-12 10:55           ` John Garry
2023-07-12 17:52             ` Ian Rogers
2023-07-13 15:06               ` John Garry
2023-07-13 21:35                 ` Ian Rogers
2023-07-14 11:58                   ` John Garry
2023-07-14 15:55                     ` Ian Rogers
2023-07-17  7:41                       ` John Garry
2023-07-17 21:39                         ` Ian Rogers
2023-07-18  9:32                           ` John Garry
2023-07-19 15:25                             ` Ian Rogers
2023-07-19 15:36                               ` John Garry
2023-07-19 15:49                                 ` Ian Rogers
2023-07-19 20:07                               ` Arnaldo Carvalho de Melo
2023-06-28 10:29 ` [PATCH RFC 5/9] perf pmu: Refactor pmu_add_sys_aliases_iter_fn() John Garry
2023-06-28 10:29 ` John Garry [this message]
2023-06-28 10:29 ` [PATCH RFC 7/9] perf metrics: Test metric match in metricgroup__sys_event_iter() John Garry
2023-06-28 10:29 ` [PATCH RFC 8/9] perf metrics: Stop metricgroup__add_metric_sys_event_iter if already matched John Garry
2023-06-28 10:29 ` [PATCH RFC 9/9] perf vendor events arm64: Remove unnecessary metric Unit and Compat specifiers John Garry
2023-06-29 22:08 ` [PATCH RFC 0/9] perf tool: sys event metric support re-write Namhyung Kim
2023-06-30  9:35   ` John Garry
2023-06-30 21:07     ` Namhyung Kim

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230628102949.2598096-7-john.g.garry@oracle.com \
    --to=john.g.garry@oracle.com \
    --cc=acme@kernel.org \
    --cc=irogers@google.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@linux.intel.com \
    --cc=kjain@linux.ibm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=namhyung@kernel.org \
    --cc=qiangqing.zhang@nxp.com \
    --cc=renyu.zj@linux.alibaba.com \
    --cc=shangxiaojing@huawei.com \
    --cc=zhangshaokun@hisilicon.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®