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 add JSON events

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>
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-14-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
e6ff1eed 7c52f10c

+85 -15
+14
tools/perf/pmu-events/empty-pmu-events.c
··· 298 298 return -1000; 299 299 } 300 300 301 + size_t pmu_events_table__num_events(const struct pmu_events_table *table, 302 + struct perf_pmu *pmu) 303 + { 304 + size_t count = 0; 305 + 306 + for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) { 307 + if (pmu && !pmu__name_match(pmu, pe->pmu)) 308 + continue; 309 + 310 + count++; 311 + } 312 + return count; 313 + } 314 + 301 315 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, 302 316 void *data) 303 317 {
+15
tools/perf/pmu-events/jevents.py
··· 909 909 return -1000; 910 910 } 911 911 912 + size_t pmu_events_table__num_events(const struct pmu_events_table *table, 913 + struct perf_pmu *pmu) 914 + { 915 + size_t count = 0; 916 + 917 + for (size_t i = 0; i < table->num_pmus; i++) { 918 + const struct pmu_table_entry *table_pmu = &table->pmus[i]; 919 + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 920 + 921 + if (pmu__name_match(pmu, pmu_name)) 922 + count += table_pmu->num_entries; 923 + } 924 + return count; 925 + } 926 + 912 927 static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table, 913 928 const struct pmu_table_entry *pmu, 914 929 pmu_metric_iter_fn fn,
+4
tools/perf/pmu-events/pmu-events.h
··· 3 3 #define PMU_EVENTS_H 4 4 5 5 #include <stdbool.h> 6 + #include <stddef.h> 6 7 7 8 struct perf_pmu; 8 9 ··· 87 86 const char *name, 88 87 pmu_event_iter_fn fn, 89 88 void *data); 89 + size_t pmu_events_table__num_events(const struct pmu_events_table *table, 90 + struct perf_pmu *pmu); 91 + 90 92 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, 91 93 void *data); 92 94
+2
tools/perf/tests/pmu-events.c
··· 546 546 547 547 pmu->events_table = table; 548 548 pmu_add_cpu_aliases_table(pmu, table); 549 + pmu->cpu_aliases_added = true; 549 550 550 551 res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL); 551 552 if (res != 0) { ··· 587 586 return -1; 588 587 pmu->events_table = events_table; 589 588 pmu_add_cpu_aliases_table(pmu, events_table); 589 + pmu->cpu_aliases_added = true; 590 590 pmu_add_sys_aliases(pmu); 591 591 592 592 /* Count how many aliases we generated */
+38 -12
tools/perf/util/pmu.c
··· 523 523 if (!pe) { 524 524 /* Update an event from sysfs with json data. */ 525 525 if (pmu->events_table) { 526 - pmu_events_table__find_event(pmu->events_table, pmu, name, 527 - update_alias, alias); 526 + if (pmu_events_table__find_event(pmu->events_table, pmu, name, 527 + update_alias, alias) == 0) 528 + pmu->loaded_json_aliases++; 528 529 } 529 530 } 530 531 ··· 549 548 "%s=%s", term->config, term->val.str); 550 549 } 551 550 alias->str = strdup(newval); 551 + if (!pe) 552 + pmu->sysfs_aliases++; 553 + else 554 + pmu->loaded_json_aliases++; 552 555 list_add_tail(&alias->list, &pmu->aliases); 553 556 return 0; 554 557 } ··· 883 878 if (!pmu->events_table) 884 879 return; 885 880 881 + if (pmu->cpu_aliases_added) 882 + return; 883 + 886 884 pmu_add_cpu_aliases_table(pmu, pmu->events_table); 885 + pmu->cpu_aliases_added = true; 887 886 } 888 887 889 888 static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, ··· 999 990 pmu->id = pmu_id(name); 1000 991 pmu->max_precise = pmu_max_precise(dirfd, pmu); 1001 992 pmu->events_table = perf_pmu__find_events_table(pmu); 1002 - pmu_add_cpu_aliases(pmu); 1003 993 pmu_add_sys_aliases(pmu); 1004 994 list_add_tail(&pmu->list, pmus); 1005 995 ··· 1376 1368 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 1377 1369 struct parse_events_term *term) 1378 1370 { 1371 + struct perf_pmu_alias *alias; 1379 1372 char *name; 1380 1373 1381 1374 if (parse_events__is_hardcoded_term(term)) ··· 1397 1388 return NULL; 1398 1389 } 1399 1390 1400 - return perf_pmu__find_alias(pmu, name); 1391 + alias = perf_pmu__find_alias(pmu, name); 1392 + if (alias || pmu->cpu_aliases_added) 1393 + return alias; 1394 + 1395 + /* Alias doesn't exist, try to get it from the json events. */ 1396 + if (pmu->events_table && 1397 + pmu_events_table__find_event(pmu->events_table, pmu, name, 1398 + pmu_add_cpu_aliases_map_callback, 1399 + pmu) == 0) { 1400 + alias = perf_pmu__find_alias(pmu, name); 1401 + } 1402 + return alias; 1401 1403 } 1402 1404 1403 1405 ··· 1575 1555 return !pmu->is_core || perf_pmus__num_core_pmus() == 1; 1576 1556 } 1577 1557 1578 - bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name) 1558 + bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) 1579 1559 { 1580 - return perf_pmu__find_alias(pmu, name) != NULL; 1560 + if (perf_pmu__find_alias(pmu, name) != NULL) 1561 + return true; 1562 + if (pmu->cpu_aliases_added || !pmu->events_table) 1563 + return false; 1564 + return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0; 1581 1565 } 1582 1566 1583 - size_t perf_pmu__num_events(const struct perf_pmu *pmu) 1567 + size_t perf_pmu__num_events(struct perf_pmu *pmu) 1584 1568 { 1585 - struct list_head *list; 1586 - size_t nr = 0; 1569 + size_t nr = pmu->sysfs_aliases; 1587 1570 1588 - list_for_each(list, &pmu->aliases) 1589 - nr++; 1571 + if (pmu->cpu_aliases_added) 1572 + nr += pmu->loaded_json_aliases; 1573 + else if (pmu->events_table) 1574 + nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases; 1590 1575 1591 1576 return pmu->selectable ? nr + 1 : nr; 1592 1577 } ··· 1629 1604 return buf; 1630 1605 } 1631 1606 1632 - int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb) 1607 + int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb) 1633 1608 { 1634 1609 char buf[1024]; 1635 1610 struct perf_pmu_alias *event; ··· 1638 1613 }; 1639 1614 int ret = 0; 1640 1615 1616 + pmu_add_cpu_aliases(pmu); 1641 1617 list_for_each_entry(event, &pmu->aliases, list) { 1642 1618 size_t buf_used; 1643 1619
+12 -3
tools/perf/util/pmu.h
··· 118 118 * @events_table: The events table for json events in pmu-events.c. 119 119 */ 120 120 const struct pmu_events_table *events_table; 121 + /** @sysfs_aliases: Number of sysfs aliases loaded. */ 122 + uint32_t sysfs_aliases; 123 + /** @sysfs_aliases: Number of json event aliases loaded. */ 124 + uint32_t loaded_json_aliases; 125 + /** 126 + * @cpu_aliases_added: Have all json events table entries for the PMU 127 + * been added? 128 + */ 129 + bool cpu_aliases_added; 121 130 /** @caps_initialized: Has the list caps been initialized? */ 122 131 bool caps_initialized; 123 132 /** @nr_caps: The length of the list caps. */ ··· 208 199 bool is_pmu_core(const char *name); 209 200 bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu); 210 201 bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu); 211 - bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name); 212 - size_t perf_pmu__num_events(const struct perf_pmu *pmu); 213 - int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb); 202 + bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name); 203 + size_t perf_pmu__num_events(struct perf_pmu *pmu); 204 + int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb); 214 205 bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name); 215 206 216 207 /**