Skip to content

Commit 7b723db

Browse files
captain5050acmel
authored andcommitted
perf pmu: Be lazy about loading event info files from sysfs
Event info is only needed when an event is parsed or when merging data from an JSON and sysfs event. Be lazy in its loading to reduce file accesses. 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-16-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent 88ed918 commit 7b723db

File tree

1 file changed

+83
-45
lines changed

1 file changed

+83
-45
lines changed

tools/perf/util/pmu.c

+83-45
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ struct perf_pmu_alias {
5858
struct list_head terms;
5959
/** @list: List element of struct perf_pmu aliases. */
6060
struct list_head list;
61+
/**
62+
* @pmu_name: The name copied from the json struct pmu_event. This can
63+
* differ from the PMU name as it won't have suffixes.
64+
*/
65+
char *pmu_name;
6166
/** @unit: Units for the event, such as bytes or cache lines. */
6267
char unit[UNIT_MAX_LEN+1];
6368
/** @scale: Value to scale read counter values by. */
@@ -79,11 +84,10 @@ struct perf_pmu_alias {
7984
* default.
8085
*/
8186
bool deprecated;
82-
/**
83-
* @pmu_name: The name copied from the json struct pmu_event. This can
84-
* differ from the PMU name as it won't have suffixes.
85-
*/
86-
char *pmu_name;
87+
/** @from_sysfs: Was the alias from sysfs or a json event? */
88+
bool from_sysfs;
89+
/** @info_loaded: Have the scale, unit and other values been read from disk? */
90+
bool info_loaded;
8791
};
8892

8993
/**
@@ -280,17 +284,21 @@ int perf_pmu__convert_scale(const char *scale, char **end, double *sval)
280284
return ret;
281285
}
282286

283-
static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, const char *name)
287+
static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
284288
{
285289
struct stat st;
286290
ssize_t sret;
291+
size_t len;
287292
char scale[128];
288293
int fd, ret = -1;
289294
char path[PATH_MAX];
290295

291-
scnprintf(path, PATH_MAX, "%s.scale", name);
296+
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
297+
if (!len)
298+
return 0;
299+
scnprintf(path + len, sizeof(path) - len, "%s/%s.scale", pmu->name, alias->name);
292300

293-
fd = openat(dirfd, path, O_RDONLY);
301+
fd = open(path, O_RDONLY);
294302
if (fd == -1)
295303
return -1;
296304

@@ -312,15 +320,20 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, const
312320
return ret;
313321
}
314322

315-
static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, const char *name)
323+
static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
316324
{
317325
char path[PATH_MAX];
326+
size_t len;
318327
ssize_t sret;
319328
int fd;
320329

321-
scnprintf(path, PATH_MAX, "%s.unit", name);
322330

323-
fd = openat(dirfd, path, O_RDONLY);
331+
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
332+
if (!len)
333+
return 0;
334+
scnprintf(path + len, sizeof(path) - len, "%s/%s.unit", pmu->name, alias->name);
335+
336+
fd = open(path, O_RDONLY);
324337
if (fd == -1)
325338
return -1;
326339

@@ -343,14 +356,18 @@ static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, const c
343356
}
344357

345358
static int
346-
perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, const char *name)
359+
perf_pmu__parse_per_pkg(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
347360
{
348361
char path[PATH_MAX];
362+
size_t len;
349363
int fd;
350364

351-
scnprintf(path, PATH_MAX, "%s.per-pkg", name);
365+
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
366+
if (!len)
367+
return 0;
368+
scnprintf(path + len, sizeof(path) - len, "%s/%s.per-pkg", pmu->name, alias->name);
352369

353-
fd = openat(dirfd, path, O_RDONLY);
370+
fd = open(path, O_RDONLY);
354371
if (fd == -1)
355372
return -1;
356373

@@ -360,15 +377,18 @@ perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, const char *nam
360377
return 0;
361378
}
362379

363-
static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
364-
int dirfd, const char *name)
380+
static int perf_pmu__parse_snapshot(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
365381
{
366382
char path[PATH_MAX];
383+
size_t len;
367384
int fd;
368385

369-
scnprintf(path, PATH_MAX, "%s.snapshot", name);
386+
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
387+
if (!len)
388+
return 0;
389+
scnprintf(path + len, sizeof(path) - len, "%s/%s.snapshot", pmu->name, alias->name);
370390

371-
fd = openat(dirfd, path, O_RDONLY);
391+
fd = open(path, O_RDONLY);
372392
if (fd == -1)
373393
return -1;
374394

@@ -429,32 +449,52 @@ static bool assign_str(const char *name, const char *field, char **old_str,
429449
return true;
430450
}
431451

452+
static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
453+
{
454+
if (!alias->from_sysfs || alias->info_loaded)
455+
return;
456+
457+
/*
458+
* load unit name and scale if available
459+
*/
460+
perf_pmu__parse_unit(pmu, alias);
461+
perf_pmu__parse_scale(pmu, alias);
462+
perf_pmu__parse_per_pkg(pmu, alias);
463+
perf_pmu__parse_snapshot(pmu, alias);
464+
}
465+
466+
struct update_alias_data {
467+
struct perf_pmu *pmu;
468+
struct perf_pmu_alias *alias;
469+
};
470+
432471
static int update_alias(const struct pmu_event *pe,
433472
const struct pmu_events_table *table __maybe_unused,
434473
void *vdata)
435474
{
436-
struct perf_pmu_alias *alias = vdata;
475+
struct update_alias_data *data = vdata;
437476
int ret = 0;
438477

439-
assign_str(pe->name, "desc", &alias->desc, pe->desc);
440-
assign_str(pe->name, "long_desc", &alias->long_desc, pe->long_desc);
441-
assign_str(pe->name, "topic", &alias->topic, pe->topic);
442-
alias->per_pkg = pe->perpkg;
443-
if (assign_str(pe->name, "value", &alias->str, pe->event)) {
444-
parse_events_terms__purge(&alias->terms);
445-
ret = parse_events_terms(&alias->terms, pe->event, /*input=*/NULL);
478+
read_alias_info(data->pmu, data->alias);
479+
assign_str(pe->name, "desc", &data->alias->desc, pe->desc);
480+
assign_str(pe->name, "long_desc", &data->alias->long_desc, pe->long_desc);
481+
assign_str(pe->name, "topic", &data->alias->topic, pe->topic);
482+
data->alias->per_pkg = pe->perpkg;
483+
if (assign_str(pe->name, "value", &data->alias->str, pe->event)) {
484+
parse_events_terms__purge(&data->alias->terms);
485+
ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL);
446486
}
447487
if (!ret && pe->unit) {
448488
char *unit;
449489

450-
ret = perf_pmu__convert_scale(pe->unit, &unit, &alias->scale);
490+
ret = perf_pmu__convert_scale(pe->unit, &unit, &data->alias->scale);
451491
if (!ret)
452-
snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
492+
snprintf(data->alias->unit, sizeof(data->alias->unit), "%s", unit);
453493
}
454494
return ret;
455495
}
456496

457-
static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name,
497+
static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
458498
const char *desc, const char *val, FILE *val_fd,
459499
const struct pmu_event *pe)
460500
{
@@ -498,16 +538,6 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
498538
}
499539

500540
alias->name = strdup(name);
501-
if (dirfd >= 0) {
502-
/*
503-
* load unit name and scale if available
504-
*/
505-
perf_pmu__parse_unit(alias, dirfd, name);
506-
perf_pmu__parse_scale(alias, dirfd, name);
507-
perf_pmu__parse_per_pkg(alias, dirfd, name);
508-
perf_pmu__parse_snapshot(alias, dirfd, name);
509-
}
510-
511541
alias->desc = desc ? strdup(desc) : NULL;
512542
alias->long_desc = long_desc ? strdup(long_desc) :
513543
desc ? strdup(desc) : NULL;
@@ -522,9 +552,15 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
522552
}
523553
if (!pe) {
524554
/* Update an event from sysfs with json data. */
555+
struct update_alias_data data = {
556+
.pmu = pmu,
557+
.alias = alias,
558+
};
559+
560+
alias->from_sysfs = true;
525561
if (pmu->events_table) {
526562
if (pmu_events_table__find_event(pmu->events_table, pmu, name,
527-
update_alias, alias) == 0)
563+
update_alias, &data) == 0)
528564
pmu->loaded_json_aliases++;
529565
}
530566
}
@@ -612,7 +648,7 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd)
612648
continue;
613649
}
614650

615-
if (perf_pmu__new_alias(pmu, dirfd, name, /*desc=*/ NULL,
651+
if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL,
616652
/*val=*/ NULL, file, /*pe=*/ NULL) < 0)
617653
pr_debug("Cannot set up %s\n", name);
618654
fclose(file);
@@ -865,7 +901,7 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
865901
{
866902
struct perf_pmu *pmu = vdata;
867903

868-
perf_pmu__new_alias(pmu, -1, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
904+
perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
869905
return 0;
870906
}
871907

@@ -901,7 +937,7 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
901937

902938
if (!strcmp(pmu->id, pe->compat) &&
903939
pmu_uncore_alias_match(pe->pmu, pmu->name)) {
904-
perf_pmu__new_alias(pmu, -1,
940+
perf_pmu__new_alias(pmu,
905941
pe->name,
906942
pe->desc,
907943
pe->event,
@@ -1417,11 +1453,13 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
14171453
}
14181454

14191455

1420-
static int check_info_data(struct perf_pmu_alias *alias,
1456+
static int check_info_data(struct perf_pmu *pmu,
1457+
struct perf_pmu_alias *alias,
14211458
struct perf_pmu_info *info,
14221459
struct parse_events_error *err,
14231460
int column)
14241461
{
1462+
read_alias_info(pmu, alias);
14251463
/*
14261464
* Only one term in event definition can
14271465
* define unit, scale and snapshot, fail
@@ -1491,7 +1529,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
14911529
return ret;
14921530
}
14931531

1494-
ret = check_info_data(alias, info, err, term->err_term);
1532+
ret = check_info_data(pmu, alias, info, err, term->err_term);
14951533
if (ret)
14961534
return ret;
14971535

0 commit comments

Comments
 (0)