Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
8d4b6d37 7b723dbb

+46 -39
+2
tools/perf/tests/pmu-events.c
··· 547 547 pmu->events_table = table; 548 548 pmu_add_cpu_aliases_table(pmu, table); 549 549 pmu->cpu_aliases_added = true; 550 + pmu->sysfs_aliases_loaded = true; 550 551 551 552 res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL); 552 553 if (res != 0) { ··· 589 588 pmu->events_table = events_table; 590 589 pmu_add_cpu_aliases_table(pmu, events_table); 591 590 pmu->cpu_aliases_added = true; 591 + pmu->sysfs_aliases_loaded = true; 592 592 pmu_add_sys_aliases(pmu); 593 593 594 594 /* Count how many aliases we generated */
+42 -39
tools/perf/util/pmu.c
··· 115 115 bool loaded; 116 116 }; 117 117 118 + static int pmu_aliases_parse(struct perf_pmu *pmu); 119 + 118 120 static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name) 119 121 { 120 122 struct perf_pmu_format *format; ··· 422 420 } 423 421 } 424 422 425 - static struct perf_pmu_alias *perf_pmu__find_alias(const struct perf_pmu *pmu, const char *name) 423 + static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, 424 + const char *name, 425 + bool load) 426 426 { 427 427 struct perf_pmu_alias *alias; 428 + 429 + if (load && !pmu->sysfs_aliases_loaded) 430 + pmu_aliases_parse(pmu); 428 431 429 432 list_for_each_entry(alias, &pmu->aliases, list) { 430 433 if (!strcasecmp(alias->name, name)) ··· 512 505 const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL; 513 506 bool deprecated = false, perpkg = false; 514 507 515 - if (perf_pmu__find_alias(pmu, name)) { 508 + if (perf_pmu__find_alias(pmu, name, /*load=*/ false)) { 516 509 /* Alias was already created/loaded. */ 517 510 return 0; 518 511 } ··· 618 611 } 619 612 620 613 /* 621 - * Process all the sysfs attributes located under the directory 622 - * specified in 'dir' parameter. 614 + * Reading the pmu event aliases definition, which should be located at: 615 + * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 623 616 */ 624 - static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd) 617 + static int pmu_aliases_parse(struct perf_pmu *pmu) 625 618 { 619 + char path[PATH_MAX]; 626 620 struct dirent *evt_ent; 627 621 DIR *event_dir; 628 - int fd; 622 + size_t len; 623 + int fd, dir_fd; 629 624 630 - event_dir = fdopendir(dirfd); 631 - if (!event_dir) 625 + len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 626 + if (!len) 627 + return 0; 628 + scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name); 629 + 630 + dir_fd = open(path, O_DIRECTORY); 631 + if (dir_fd == -1) { 632 + pmu->sysfs_aliases_loaded = true; 633 + return 0; 634 + } 635 + 636 + event_dir = fdopendir(dir_fd); 637 + if (!event_dir){ 638 + close (dir_fd); 632 639 return -EINVAL; 640 + } 633 641 634 642 while ((evt_ent = readdir(event_dir))) { 635 643 char *name = evt_ent->d_name; ··· 659 637 if (pmu_alias_info_file(name)) 660 638 continue; 661 639 662 - fd = openat(dirfd, name, O_RDONLY); 640 + fd = openat(dir_fd, name, O_RDONLY); 663 641 if (fd == -1) { 664 642 pr_debug("Cannot open %s\n", name); 665 643 continue; ··· 677 655 } 678 656 679 657 closedir(event_dir); 680 - return 0; 681 - } 682 - 683 - /* 684 - * Reading the pmu event aliases definition, which should be located at: 685 - * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 686 - */ 687 - static int pmu_aliases(struct perf_pmu *pmu, int dirfd, const char *name) 688 - { 689 - int fd; 690 - 691 - fd = perf_pmu__pathname_fd(dirfd, name, "events", O_DIRECTORY); 692 - if (fd < 0) 693 - return 0; 694 - 695 - /* it'll close the fd */ 696 - if (pmu_aliases_parse(pmu, fd)) 697 - return -1; 698 - 658 + close (dir_fd); 659 + pmu->sysfs_aliases_loaded = true; 699 660 return 0; 700 661 } 701 662 ··· 1019 1014 * now. 1020 1015 */ 1021 1016 if (pmu_format(pmu, dirfd, name)) { 1022 - free(pmu); 1023 - return NULL; 1024 - } 1025 - /* 1026 - * Check the aliases first to avoid unnecessary work. 1027 - */ 1028 - if (pmu_aliases(pmu, dirfd, name)) { 1029 1017 free(pmu); 1030 1018 return NULL; 1031 1019 } ··· 1436 1438 return NULL; 1437 1439 } 1438 1440 1439 - alias = perf_pmu__find_alias(pmu, name); 1441 + alias = perf_pmu__find_alias(pmu, name, /*load=*/ true); 1440 1442 if (alias || pmu->cpu_aliases_added) 1441 1443 return alias; 1442 1444 ··· 1445 1447 pmu_events_table__find_event(pmu->events_table, pmu, name, 1446 1448 pmu_add_cpu_aliases_map_callback, 1447 1449 pmu) == 0) { 1448 - alias = perf_pmu__find_alias(pmu, name); 1450 + alias = perf_pmu__find_alias(pmu, name, /*load=*/ false); 1449 1451 } 1450 1452 return alias; 1451 1453 } ··· 1618 1620 1619 1621 bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) 1620 1622 { 1621 - if (perf_pmu__find_alias(pmu, name) != NULL) 1623 + if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL) 1622 1624 return true; 1623 1625 if (pmu->cpu_aliases_added || !pmu->events_table) 1624 1626 return false; ··· 1627 1629 1628 1630 size_t perf_pmu__num_events(struct perf_pmu *pmu) 1629 1631 { 1630 - size_t nr = pmu->sysfs_aliases; 1632 + size_t nr; 1633 + 1634 + if (!pmu->sysfs_aliases_loaded) 1635 + pmu_aliases_parse(pmu); 1636 + 1637 + nr = pmu->sysfs_aliases; 1631 1638 1632 1639 if (pmu->cpu_aliases_added) 1633 1640 nr += pmu->loaded_json_aliases;
+2
tools/perf/util/pmu.h
··· 122 122 uint32_t sysfs_aliases; 123 123 /** @sysfs_aliases: Number of json event aliases loaded. */ 124 124 uint32_t loaded_json_aliases; 125 + /** @sysfs_aliases_loaded: Are sysfs aliases loaded from disk? */ 126 + bool sysfs_aliases_loaded; 125 127 /** 126 128 * @cpu_aliases_added: Have all json events table entries for the PMU 127 129 * been added?