diff options
author | Ian Rogers <irogers@google.com> | 2023-08-24 06:13:28 +0200 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2023-08-24 16:10:27 +0200 |
commit | 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53 (patch) | |
tree | c39d7ee6301ac6dc5690b89f2e00b124eee33362 | |
parent | perf pmu: Be lazy about loading event info files from sysfs (diff) | |
download | linux-8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53.tar.xz linux-8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53.zip |
perf pmu: Lazily load sysfs aliases
Don't load sysfs aliases for a PMU when the PMU is first created, defer
until an alias needs to be found. For the pmu-scan benchmark, average
core PMU scanning is reduced by 30.8%, and average PMU scanning by
12.6%.
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20230824041330.266337-17-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/tests/pmu-events.c | 2 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 81 | ||||
-rw-r--r-- | tools/perf/util/pmu.h | 2 |
3 files changed, 46 insertions, 39 deletions
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index 9ac893ae5f0d..3dc1ebee4d9f 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -547,6 +547,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; + pmu->sysfs_aliases_loaded = true; res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL); if (res != 0) { @@ -588,6 +589,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu) pmu->events_table = events_table; pmu_add_cpu_aliases_table(pmu, events_table); pmu->cpu_aliases_added = true; + pmu->sysfs_aliases_loaded = 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 493d3e59fd50..bb2ca29cd7bd 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -115,6 +115,8 @@ struct perf_pmu_format { bool loaded; }; +static int pmu_aliases_parse(struct perf_pmu *pmu); + static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name) { struct perf_pmu_format *format; @@ -420,10 +422,15 @@ static void perf_pmu__del_aliases(struct perf_pmu *pmu) } } -static struct perf_pmu_alias *perf_pmu__find_alias(const struct perf_pmu *pmu, const char *name) +static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, + const char *name, + bool load) { struct perf_pmu_alias *alias; + if (load && !pmu->sysfs_aliases_loaded) + pmu_aliases_parse(pmu); + list_for_each_entry(alias, &pmu->aliases, list) { if (!strcasecmp(alias->name, name)) return alias; @@ -505,7 +512,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL; bool deprecated = false, perpkg = false; - if (perf_pmu__find_alias(pmu, name)) { + if (perf_pmu__find_alias(pmu, name, /*load=*/ false)) { /* Alias was already created/loaded. */ return 0; } @@ -611,18 +618,33 @@ static inline bool pmu_alias_info_file(char *name) } /* - * Process all the sysfs attributes located under the directory - * specified in 'dir' parameter. + * Reading the pmu event aliases definition, which should be located at: + * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. */ -static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd) +static int pmu_aliases_parse(struct perf_pmu *pmu) { + char path[PATH_MAX]; struct dirent *evt_ent; DIR *event_dir; - int fd; + size_t len; + int fd, dir_fd; - event_dir = fdopendir(dirfd); - if (!event_dir) + len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); + if (!len) + return 0; + scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name); + + dir_fd = open(path, O_DIRECTORY); + if (dir_fd == -1) { + pmu->sysfs_aliases_loaded = true; + return 0; + } + + event_dir = fdopendir(dir_fd); + if (!event_dir){ + close (dir_fd); return -EINVAL; + } while ((evt_ent = readdir(event_dir))) { char *name = evt_ent->d_name; @@ -637,7 +659,7 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd) if (pmu_alias_info_file(name)) continue; - fd = openat(dirfd, name, O_RDONLY); + fd = openat(dir_fd, name, O_RDONLY); if (fd == -1) { pr_debug("Cannot open %s\n", name); continue; @@ -655,25 +677,8 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd) } closedir(event_dir); - return 0; -} - -/* - * Reading the pmu event aliases definition, which should be located at: - * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. - */ -static int pmu_aliases(struct perf_pmu *pmu, int dirfd, const char *name) -{ - int fd; - - fd = perf_pmu__pathname_fd(dirfd, name, "events", O_DIRECTORY); - if (fd < 0) - return 0; - - /* it'll close the fd */ - if (pmu_aliases_parse(pmu, fd)) - return -1; - + close (dir_fd); + pmu->sysfs_aliases_loaded = true; return 0; } @@ -1017,13 +1022,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char free(pmu); return NULL; } - /* - * Check the aliases first to avoid unnecessary work. - */ - if (pmu_aliases(pmu, dirfd, name)) { - free(pmu); - return NULL; - } pmu->is_core = is_pmu_core(name); pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); @@ -1438,7 +1436,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, return NULL; } - alias = perf_pmu__find_alias(pmu, name); + alias = perf_pmu__find_alias(pmu, name, /*load=*/ true); if (alias || pmu->cpu_aliases_added) return alias; @@ -1447,7 +1445,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 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); + alias = perf_pmu__find_alias(pmu, name, /*load=*/ false); } return alias; } @@ -1620,7 +1618,7 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) { - if (perf_pmu__find_alias(pmu, name) != NULL) + if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL) return true; if (pmu->cpu_aliases_added || !pmu->events_table) return false; @@ -1629,7 +1627,12 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) size_t perf_pmu__num_events(struct perf_pmu *pmu) { - size_t nr = pmu->sysfs_aliases; + size_t nr; + + if (!pmu->sysfs_aliases_loaded) + pmu_aliases_parse(pmu); + + nr = pmu->sysfs_aliases; if (pmu->cpu_aliases_added) nr += pmu->loaded_json_aliases; diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 288d2908382a..bae0de3ed7a5 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -122,6 +122,8 @@ struct perf_pmu { uint32_t sysfs_aliases; /** @sysfs_aliases: Number of json event aliases loaded. */ uint32_t loaded_json_aliases; + /** @sysfs_aliases_loaded: Are sysfs aliases loaded from disk? */ + bool sysfs_aliases_loaded; /** * @cpu_aliases_added: Have all json events table entries for the PMU * been added? |