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-events: Reduce processed events by passing PMU

Pass the PMU to pmu_events_table__for_each_event so that entries that
don't match don't need to be processed by callback.

If a NULL PMU is passed then all PMUs are processed.

'perf bench internals pmu-scan's "Average PMU scanning" performance is
reduced by about 5% on an Intel tigerlake.

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

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
e3edd6cf c4ac7f75

+41 -38
+10 -5
tools/perf/pmu-events/empty-pmu-events.c
··· 266 266 }, 267 267 }; 268 268 269 - int pmu_events_table__for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn, 270 - void *data) 269 + int pmu_events_table__for_each_event(const struct pmu_events_table *table, struct perf_pmu *pmu, 270 + pmu_event_iter_fn fn, void *data) 271 271 { 272 272 for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) { 273 - int ret = fn(pe, table, data); 273 + int ret; 274 274 275 + if (pmu && !pmu__name_match(pmu, pe->pmu)) 276 + continue; 277 + 278 + ret = fn(pe, table, data); 275 279 if (ret) 276 280 return ret; 277 281 } ··· 375 371 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) 376 372 { 377 373 for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->arch; tables++) { 378 - int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data); 374 + int ret = pmu_events_table__for_each_event(&tables->event_table, 375 + /*pmu=*/ NULL, fn, data); 379 376 380 377 if (ret) 381 378 return ret; ··· 413 408 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 414 409 tables->name; 415 410 tables++) { 416 - int ret = pmu_events_table__for_each_event(&tables->table, fn, data); 411 + int ret = pmu_events_table__for_each_event(&tables->table, /*pmu=*/ NULL, fn, data); 417 412 418 413 if (ret) 419 414 return ret;
+13 -5
tools/perf/pmu-events/jevents.py
··· 826 826 } 827 827 828 828 int pmu_events_table__for_each_event(const struct pmu_events_table *table, 829 + struct perf_pmu *pmu, 829 830 pmu_event_iter_fn fn, 830 831 void *data) 831 832 { 832 833 for (size_t i = 0; i < table->num_pmus; i++) { 833 - int ret = pmu_events_table__for_each_event_pmu(table, &table->pmus[i], 834 - fn, data); 834 + const struct pmu_table_entry *table_pmu = &table->pmus[i]; 835 + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 836 + int ret; 835 837 836 - if (ret) 838 + if (pmu && !pmu__name_match(pmu, pmu_name)) 839 + continue; 840 + 841 + ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); 842 + if (pmu || ret) 837 843 return ret; 838 844 } 839 845 return 0; ··· 961 955 for (const struct pmu_events_map *tables = &pmu_events_map[0]; 962 956 tables->arch; 963 957 tables++) { 964 - int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data); 958 + int ret = pmu_events_table__for_each_event(&tables->event_table, 959 + /*pmu=*/ NULL, fn, data); 965 960 966 961 if (ret) 967 962 return ret; ··· 999 992 for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; 1000 993 tables->name; 1001 994 tables++) { 1002 - int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data); 995 + int ret = pmu_events_table__for_each_event(&tables->event_table, 996 + /*pmu=*/ NULL, fn, data); 1003 997 1004 998 if (ret) 1005 999 return ret;
+3 -1
tools/perf/pmu-events/pmu-events.h
··· 77 77 const struct pmu_metrics_table *table, 78 78 void *data); 79 79 80 - int pmu_events_table__for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn, 80 + int pmu_events_table__for_each_event(const struct pmu_events_table *table, 81 + struct perf_pmu *pmu, 82 + pmu_event_iter_fn fn, 81 83 void *data); 82 84 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, 83 85 void *data);
+4 -2
tools/perf/tests/pmu-events.c
··· 483 483 if (!table || !sys_event_table) 484 484 return -1; 485 485 486 - err = pmu_events_table__for_each_event(table, test__pmu_event_table_core_callback, 486 + err = pmu_events_table__for_each_event(table, /*pmu=*/ NULL, 487 + test__pmu_event_table_core_callback, 487 488 &map_events); 488 489 if (err) 489 490 return err; 490 491 491 - err = pmu_events_table__for_each_event(sys_event_table, test__pmu_event_table_sys_callback, 492 + err = pmu_events_table__for_each_event(sys_event_table, /*pmu=*/ NULL, 493 + test__pmu_event_table_sys_callback, 492 494 &map_events); 493 495 if (err) 494 496 return err;
+10 -25
tools/perf/util/pmu.c
··· 859 859 return res; 860 860 } 861 861 862 - struct pmu_add_cpu_aliases_map_data { 863 - /* List being added to. */ 864 - struct list_head *head; 865 - /* If a pmu_event lacks a given PMU the default used. */ 866 - char *default_pmu_name; 867 - /* The PMU that we're searching for events for. */ 868 - struct perf_pmu *pmu; 869 - }; 870 - 871 862 static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, 872 863 const struct pmu_events_table *table __maybe_unused, 873 864 void *vdata) 874 865 { 875 - struct pmu_add_cpu_aliases_map_data *data = vdata; 876 - const char *pname = pe->pmu ?: data->default_pmu_name; 866 + struct list_head *head = vdata; 877 867 878 - if (!strcmp(pname, data->pmu->name) || 879 - (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->pmu->name))) { 880 - /* need type casts to override 'const' */ 881 - __perf_pmu__new_alias(data->head, -1, (char *)pe->name, (char *)pe->desc, 882 - (char *)pe->event, pe); 883 - } 868 + /* need type casts to override 'const' */ 869 + __perf_pmu__new_alias(head, -1, (char *)pe->name, (char *)pe->desc, (char *)pe->event, pe); 884 870 return 0; 885 871 } 886 872 ··· 876 890 */ 877 891 void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table) 878 892 { 879 - struct pmu_add_cpu_aliases_map_data data = { 880 - .head = &pmu->aliases, 881 - .default_pmu_name = perf_pmus__default_pmu_name(), 882 - .pmu = pmu, 883 - }; 884 - 885 - pmu_events_table__for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); 886 - free(data.default_pmu_name); 893 + pmu_events_table__for_each_event(table, pmu, pmu_add_cpu_aliases_map_callback, &pmu->aliases); 887 894 } 888 895 889 896 static void pmu_add_cpu_aliases(struct perf_pmu *pmu) ··· 1690 1711 ret = cb(state, &info); 1691 1712 } 1692 1713 return ret; 1714 + } 1715 + 1716 + bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name) 1717 + { 1718 + return !strcmp(pmu->name, pmu_name) || 1719 + (pmu->is_uncore && pmu_uncore_alias_match(pmu_name, pmu->name)); 1693 1720 } 1694 1721 1695 1722 bool perf_pmu__is_software(const struct perf_pmu *pmu)
+1
tools/perf/util/pmu.h
··· 198 198 bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name); 199 199 size_t perf_pmu__num_events(const struct perf_pmu *pmu); 200 200 int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb); 201 + bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name); 201 202 202 203 /** 203 204 * perf_pmu_is_software - is the PMU a software PMU as in it uses the