Commit 8d4b6d37 authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo

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: default avatarIan 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.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 7b723dbb
...@@ -547,6 +547,7 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count) ...@@ -547,6 +547,7 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
pmu->events_table = table; pmu->events_table = table;
pmu_add_cpu_aliases_table(pmu, table); pmu_add_cpu_aliases_table(pmu, table);
pmu->cpu_aliases_added = true; pmu->cpu_aliases_added = true;
pmu->sysfs_aliases_loaded = true;
res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL); res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL);
if (res != 0) { if (res != 0) {
...@@ -588,6 +589,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu) ...@@ -588,6 +589,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
pmu->events_table = events_table; pmu->events_table = events_table;
pmu_add_cpu_aliases_table(pmu, events_table); pmu_add_cpu_aliases_table(pmu, events_table);
pmu->cpu_aliases_added = true; pmu->cpu_aliases_added = true;
pmu->sysfs_aliases_loaded = true;
pmu_add_sys_aliases(pmu); pmu_add_sys_aliases(pmu);
/* Count how many aliases we generated */ /* Count how many aliases we generated */
......
...@@ -115,6 +115,8 @@ struct perf_pmu_format { ...@@ -115,6 +115,8 @@ struct perf_pmu_format {
bool loaded; 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) static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name)
{ {
struct perf_pmu_format *format; struct perf_pmu_format *format;
...@@ -420,10 +422,15 @@ static void perf_pmu__del_aliases(struct perf_pmu *pmu) ...@@ -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; struct perf_pmu_alias *alias;
if (load && !pmu->sysfs_aliases_loaded)
pmu_aliases_parse(pmu);
list_for_each_entry(alias, &pmu->aliases, list) { list_for_each_entry(alias, &pmu->aliases, list) {
if (!strcasecmp(alias->name, name)) if (!strcasecmp(alias->name, name))
return alias; return alias;
...@@ -505,7 +512,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, ...@@ -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; const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL;
bool deprecated = false, perpkg = false; 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. */ /* Alias was already created/loaded. */
return 0; return 0;
} }
...@@ -611,18 +618,33 @@ static inline bool pmu_alias_info_file(char *name) ...@@ -611,18 +618,33 @@ static inline bool pmu_alias_info_file(char *name)
} }
/* /*
* Process all the sysfs attributes located under the directory * Reading the pmu event aliases definition, which should be located at:
* specified in 'dir' parameter. * /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; struct dirent *evt_ent;
DIR *event_dir; DIR *event_dir;
int fd; size_t len;
int fd, dir_fd;
event_dir = fdopendir(dirfd); len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
if (!event_dir) 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; return -EINVAL;
}
while ((evt_ent = readdir(event_dir))) { while ((evt_ent = readdir(event_dir))) {
char *name = evt_ent->d_name; char *name = evt_ent->d_name;
...@@ -637,7 +659,7 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd) ...@@ -637,7 +659,7 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd)
if (pmu_alias_info_file(name)) if (pmu_alias_info_file(name))
continue; continue;
fd = openat(dirfd, name, O_RDONLY); fd = openat(dir_fd, name, O_RDONLY);
if (fd == -1) { if (fd == -1) {
pr_debug("Cannot open %s\n", name); pr_debug("Cannot open %s\n", name);
continue; continue;
...@@ -655,25 +677,8 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd) ...@@ -655,25 +677,8 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd)
} }
closedir(event_dir); closedir(event_dir);
return 0; close (dir_fd);
} pmu->sysfs_aliases_loaded = true;
/*
* 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;
return 0; return 0;
} }
...@@ -1017,13 +1022,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char ...@@ -1017,13 +1022,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
free(pmu); free(pmu);
return NULL; 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->is_core = is_pmu_core(name);
pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); 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, ...@@ -1438,7 +1436,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
return NULL; return NULL;
} }
alias = perf_pmu__find_alias(pmu, name); alias = perf_pmu__find_alias(pmu, name, /*load=*/ true);
if (alias || pmu->cpu_aliases_added) if (alias || pmu->cpu_aliases_added)
return alias; return alias;
...@@ -1447,7 +1445,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, ...@@ -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_events_table__find_event(pmu->events_table, pmu, name,
pmu_add_cpu_aliases_map_callback, pmu_add_cpu_aliases_map_callback,
pmu) == 0) { pmu) == 0) {
alias = perf_pmu__find_alias(pmu, name); alias = perf_pmu__find_alias(pmu, name, /*load=*/ false);
} }
return alias; return alias;
} }
...@@ -1620,7 +1618,7 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) ...@@ -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) 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; return true;
if (pmu->cpu_aliases_added || !pmu->events_table) if (pmu->cpu_aliases_added || !pmu->events_table)
return false; return false;
...@@ -1629,7 +1627,12 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) ...@@ -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 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) if (pmu->cpu_aliases_added)
nr += pmu->loaded_json_aliases; nr += pmu->loaded_json_aliases;
......
...@@ -122,6 +122,8 @@ struct perf_pmu { ...@@ -122,6 +122,8 @@ struct perf_pmu {
uint32_t sysfs_aliases; uint32_t sysfs_aliases;
/** @sysfs_aliases: Number of json event aliases loaded. */ /** @sysfs_aliases: Number of json event aliases loaded. */
uint32_t loaded_json_aliases; 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 * @cpu_aliases_added: Have all json events table entries for the PMU
* been added? * been added?
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment