linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>, Namhyung Kim <namhyung@kernel.org>,
	Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	James Clark <james.clark@arm.com>,
	Kan Liang <kan.liang@linux.intel.com>,
	John Garry <john.g.garry@oracle.com>,
	Kajol Jain <kjain@linux.ibm.com>,
	Jing Zhang <renyu.zj@linux.alibaba.com>,
	Ravi Bangoria <ravi.bangoria@amd.com>,
	Rob Herring <robh@kernel.org>,
	Gaosheng Cui <cuigaosheng1@huawei.com>,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 13/18] perf pmu: Lazily add json events
Date: Wed, 23 Aug 2023 21:13:25 -0700	[thread overview]
Message-ID: <20230824041330.266337-14-irogers@google.com> (raw)
In-Reply-To: <20230824041330.266337-1-irogers@google.com>

Rather than scanning all json events and adding them when a PMU is
created, add the alias when the json event is needed.

Average core PMU scanning run time reduced by 60.2%. Average PMU
scanning run time reduced by 15%. Page faults with no events reduced
by 74 page faults, 4% of total.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/pmu-events/empty-pmu-events.c | 14 +++++++
 tools/perf/pmu-events/jevents.py         | 15 +++++++
 tools/perf/pmu-events/pmu-events.h       |  4 ++
 tools/perf/tests/pmu-events.c            |  2 +
 tools/perf/util/pmu.c                    | 50 ++++++++++++++++++------
 tools/perf/util/pmu.h                    | 15 +++++--
 6 files changed, 85 insertions(+), 15 deletions(-)

diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index ef18d403f25f..12bd043a05e3 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -298,6 +298,20 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
         return -1000;
 }
 
+size_t pmu_events_table__num_events(const struct pmu_events_table *table,
+                                    struct perf_pmu *pmu)
+{
+        size_t count = 0;
+
+	for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
+                if (pmu && !pmu__name_match(pmu, pe->pmu))
+                        continue;
+
+		count++;
+	}
+        return count;
+}
+
 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				      void *data)
 {
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index f07864fabd54..01335a452e70 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -909,6 +909,21 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
         return -1000;
 }
 
+size_t pmu_events_table__num_events(const struct pmu_events_table *table,
+                                    struct perf_pmu *pmu)
+{
+        size_t count = 0;
+
+        for (size_t i = 0; i < table->num_pmus; i++) {
+                const struct pmu_table_entry *table_pmu = &table->pmus[i];
+                const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
+
+                if (pmu__name_match(pmu, pmu_name))
+                        count += table_pmu->num_entries;
+        }
+        return count;
+}
+
 static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
                                                 const struct pmu_table_entry *pmu,
                                                 pmu_metric_iter_fn fn,
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index 9882b7125761..f5aa96f1685c 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -3,6 +3,7 @@
 #define PMU_EVENTS_H
 
 #include <stdbool.h>
+#include <stddef.h>
 
 struct perf_pmu;
 
@@ -86,6 +87,9 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
                                  const char *name,
                                  pmu_event_iter_fn fn,
 				 void *data);
+size_t pmu_events_table__num_events(const struct pmu_events_table *table,
+				    struct perf_pmu *pmu);
+
 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				     void *data);
 
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 4fcb84fd1f65..9ac893ae5f0d 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -546,6 +546,7 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
 
 	pmu->events_table = table;
 	pmu_add_cpu_aliases_table(pmu, table);
+	pmu->cpu_aliases_added = true;
 
 	res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL);
 	if (res != 0) {
@@ -586,6 +587,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
 		return -1;
 	pmu->events_table = events_table;
 	pmu_add_cpu_aliases_table(pmu, events_table);
+	pmu->cpu_aliases_added = true;
 	pmu_add_sys_aliases(pmu);
 
 	/* Count how many aliases we generated */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 685903c1970b..b6a118226541 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -523,8 +523,9 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 	if (!pe) {
 		/* Update an event from sysfs with json data. */
 		if (pmu->events_table) {
-			pmu_events_table__find_event(pmu->events_table, pmu, name,
-						     update_alias, alias);
+			if (pmu_events_table__find_event(pmu->events_table, pmu, name,
+							 update_alias, alias) == 0)
+				pmu->loaded_json_aliases++;
 		}
 	}
 
@@ -548,6 +549,10 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 					 "%s=%s", term->config, term->val.str);
 	}
 	alias->str = strdup(newval);
+	if (!pe)
+		pmu->sysfs_aliases++;
+	else
+		pmu->loaded_json_aliases++;
 	list_add_tail(&alias->list, &pmu->aliases);
 	return 0;
 }
@@ -878,7 +883,11 @@ static void pmu_add_cpu_aliases(struct perf_pmu *pmu)
 	if (!pmu->events_table)
 		return;
 
+	if (pmu->cpu_aliases_added)
+		return;
+
 	pmu_add_cpu_aliases_table(pmu, pmu->events_table);
+	pmu->cpu_aliases_added = true;
 }
 
 static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
@@ -990,7 +999,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
 		pmu->id = pmu_id(name);
 	pmu->max_precise = pmu_max_precise(dirfd, pmu);
 	pmu->events_table = perf_pmu__find_events_table(pmu);
-	pmu_add_cpu_aliases(pmu);
 	pmu_add_sys_aliases(pmu);
 	list_add_tail(&pmu->list, pmus);
 
@@ -1368,6 +1376,7 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 					     struct parse_events_term *term)
 {
+	struct perf_pmu_alias *alias;
 	char *name;
 
 	if (parse_events__is_hardcoded_term(term))
@@ -1388,7 +1397,18 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 		return NULL;
 	}
 
-	return perf_pmu__find_alias(pmu, name);
+	alias = perf_pmu__find_alias(pmu, name);
+	if (alias || pmu->cpu_aliases_added)
+		return alias;
+
+	/* Alias doesn't exist, try to get it from the json events. */
+	if (pmu->events_table &&
+	    pmu_events_table__find_event(pmu->events_table, pmu, name,
+				         pmu_add_cpu_aliases_map_callback,
+				         pmu) == 0) {
+		alias = perf_pmu__find_alias(pmu, name);
+	}
+	return alias;
 }
 
 
@@ -1555,18 +1575,23 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu)
 	return !pmu->is_core || perf_pmus__num_core_pmus() == 1;
 }
 
-bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name)
+bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
 {
-	return perf_pmu__find_alias(pmu, name) != NULL;
+	if (perf_pmu__find_alias(pmu, name) != NULL)
+		return true;
+	if (pmu->cpu_aliases_added || !pmu->events_table)
+		return false;
+	return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0;
 }
 
-size_t perf_pmu__num_events(const struct perf_pmu *pmu)
+size_t perf_pmu__num_events(struct perf_pmu *pmu)
 {
-	struct list_head *list;
-	size_t nr = 0;
+	size_t nr = pmu->sysfs_aliases;
 
-	list_for_each(list, &pmu->aliases)
-		nr++;
+	if (pmu->cpu_aliases_added)
+		 nr += pmu->loaded_json_aliases;
+	else if (pmu->events_table)
+		nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases;
 
 	return pmu->selectable ? nr + 1 : nr;
 }
@@ -1604,7 +1629,7 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,
 	return buf;
 }
 
-int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb)
+int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb)
 {
 	char buf[1024];
 	struct perf_pmu_alias *event;
@@ -1613,6 +1638,7 @@ int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_
 	};
 	int ret = 0;
 
+	pmu_add_cpu_aliases(pmu);
 	list_for_each_entry(event, &pmu->aliases, list) {
 		size_t buf_used;
 
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6bf0fbde4e85..288d2908382a 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -118,6 +118,15 @@ struct perf_pmu {
 	 * @events_table: The events table for json events in pmu-events.c.
 	 */
 	const struct pmu_events_table *events_table;
+	/** @sysfs_aliases: Number of sysfs aliases loaded. */
+	uint32_t sysfs_aliases;
+	/** @sysfs_aliases: Number of json event aliases loaded. */
+	uint32_t loaded_json_aliases;
+	/**
+	 * @cpu_aliases_added: Have all json events table entries for the PMU
+	 * been added?
+	 */
+	bool cpu_aliases_added;
 	/** @caps_initialized: Has the list caps been initialized? */
 	bool caps_initialized;
 	/** @nr_caps: The length of the list caps. */
@@ -199,9 +208,9 @@ bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
 bool is_pmu_core(const char *name);
 bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);
 bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu);
-bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name);
-size_t perf_pmu__num_events(const struct perf_pmu *pmu);
-int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb);
+bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name);
+size_t perf_pmu__num_events(struct perf_pmu *pmu);
+int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb);
 bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name);
 
 /**
-- 
2.42.0.rc1.204.g551eb34607-goog


  parent reply	other threads:[~2023-08-24  4:15 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
2023-08-24  4:13 ` [PATCH v2 01/18] perf pmu: Make the loading of formats lazy Ian Rogers
2023-08-24  4:13 ` [PATCH v2 02/18] perf pmu: Abstract alias/event struct Ian Rogers
2023-08-24  4:13 ` [PATCH v2 03/18] perf pmu-events: Add extra underscore to function names Ian Rogers
2023-08-24  4:13 ` [PATCH v2 04/18] perf jevents: Group events by PMU Ian Rogers
2023-08-29 15:28   ` James Clark
2023-08-29 15:34     ` Ian Rogers
2023-08-24  4:13 ` [PATCH v2 05/18] perf parse-events: Improve error message for double setting Ian Rogers
2023-08-24  4:13 ` [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs Ian Rogers
2023-08-24 13:59   ` Arnaldo Carvalho de Melo
2023-08-24 17:31     ` Ian Rogers
2023-08-25  8:19     ` Thomas Richter
2023-08-25 13:14       ` Ian Rogers
2023-08-25 14:39         ` Thomas Richter
2023-08-25 20:56           ` Arnaldo Carvalho de Melo
2023-08-25 22:56             ` Ian Rogers
2023-08-26  1:38               ` Arnaldo Carvalho de Melo
2023-08-26  6:28                 ` Ian Rogers
2023-08-28 17:44               ` Arnaldo Carvalho de Melo
2023-08-28 17:53                 ` Arnaldo Carvalho de Melo
2023-08-28 21:39                   ` Arnaldo Carvalho de Melo
2023-08-29  0:59                   ` Ian Rogers
2023-08-29  9:20                     ` Jing Zhang
2023-08-29 13:20                       ` Arnaldo Carvalho de Melo
2023-08-29 11:28                     ` Arnaldo Carvalho de Melo
2023-08-24  4:13 ` [PATCH v2 07/18] perf pmu-events: Reduce processed events by passing PMU Ian Rogers
2023-08-24  4:13 ` [PATCH v2 08/18] perf pmu-events: Add pmu_events_table__find_event Ian Rogers
2023-08-24  4:13 ` [PATCH v2 09/18] perf pmu: Parse sysfs events directly from a file Ian Rogers
2023-08-24  4:13 ` [PATCH v2 10/18] perf pmu: Prefer passing pmu to aliases list Ian Rogers
2023-08-24  4:13 ` [PATCH v2 11/18] perf pmu: Merge json events with sysfs at load time Ian Rogers
2023-08-24  4:13 ` [PATCH v2 12/18] perf pmu: Cache json events table Ian Rogers
2023-08-24  4:13 ` Ian Rogers [this message]
2023-08-24  4:13 ` [PATCH v2 14/18] perf pmu: Scan type early to fail an invalid PMU quickly Ian Rogers
2023-08-24  4:13 ` [PATCH v2 15/18] perf pmu: Be lazy about loading event info files from sysfs Ian Rogers
2023-08-24  4:13 ` [PATCH v2 16/18] perf pmu: Lazily load sysfs aliases Ian Rogers
2023-08-24  4:13 ` [PATCH v2 17/18] perf jevents: Sort strings in the big C string to reduce faults Ian Rogers
2023-08-24  4:13 ` [PATCH v2 18/18] perf jevents: Don't append Unit to desc Ian Rogers
2023-08-24 14:52 ` [PATCH v2 00/18] Lazily load PMU data Arnaldo Carvalho de Melo
2023-08-24 18:01   ` Ian Rogers

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=20230824041330.266337-14-irogers@google.com \
    --to=irogers@google.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=cuigaosheng1@huawei.com \
    --cc=james.clark@arm.com \
    --cc=john.g.garry@oracle.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@linux.intel.com \
    --cc=kjain@linux.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=ravi.bangoria@amd.com \
    --cc=renyu.zj@linux.alibaba.com \
    --cc=robh@kernel.org \
    /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;
as well as URLs for NNTP newsgroup(s).