Skip to content

Commit e6ff1ee

Browse files
captain5050acmel
authored andcommitted
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 <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Gaosheng Cui <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jing Zhang <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: John Garry <[email protected]> Cc: Kajol Jain <[email protected]> Cc: Kan Liang <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Rob Herring <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 7c52f10 commit e6ff1ee

File tree

6 files changed

+85
-15
lines changed

6 files changed

+85
-15
lines changed

tools/perf/pmu-events/empty-pmu-events.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,20 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
298298
return -1000;
299299
}
300300

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+
301315
int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
302316
void *data)
303317
{

tools/perf/pmu-events/jevents.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,21 @@ def print_system_mapping_table() -> None:
909909
return -1000;
910910
}
911911
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+
912927
static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
913928
const struct pmu_table_entry *pmu,
914929
pmu_metric_iter_fn fn,

tools/perf/pmu-events/pmu-events.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#define PMU_EVENTS_H
44

55
#include <stdbool.h>
6+
#include <stddef.h>
67

78
struct perf_pmu;
89

@@ -86,6 +87,9 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
8687
const char *name,
8788
pmu_event_iter_fn fn,
8889
void *data);
90+
size_t pmu_events_table__num_events(const struct pmu_events_table *table,
91+
struct perf_pmu *pmu);
92+
8993
int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
9094
void *data);
9195

tools/perf/tests/pmu-events.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
546546

547547
pmu->events_table = table;
548548
pmu_add_cpu_aliases_table(pmu, table);
549+
pmu->cpu_aliases_added = true;
549550

550551
res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL);
551552
if (res != 0) {
@@ -586,6 +587,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
586587
return -1;
587588
pmu->events_table = events_table;
588589
pmu_add_cpu_aliases_table(pmu, events_table);
590+
pmu->cpu_aliases_added = true;
589591
pmu_add_sys_aliases(pmu);
590592

591593
/* Count how many aliases we generated */

tools/perf/util/pmu.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,9 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
523523
if (!pe) {
524524
/* Update an event from sysfs with json data. */
525525
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++;
528529
}
529530
}
530531

@@ -548,6 +549,10 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
548549
"%s=%s", term->config, term->val.str);
549550
}
550551
alias->str = strdup(newval);
552+
if (!pe)
553+
pmu->sysfs_aliases++;
554+
else
555+
pmu->loaded_json_aliases++;
551556
list_add_tail(&alias->list, &pmu->aliases);
552557
return 0;
553558
}
@@ -878,7 +883,11 @@ static void pmu_add_cpu_aliases(struct perf_pmu *pmu)
878883
if (!pmu->events_table)
879884
return;
880885

886+
if (pmu->cpu_aliases_added)
887+
return;
888+
881889
pmu_add_cpu_aliases_table(pmu, pmu->events_table);
890+
pmu->cpu_aliases_added = true;
882891
}
883892

884893
static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
@@ -990,7 +999,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
990999
pmu->id = pmu_id(name);
9911000
pmu->max_precise = pmu_max_precise(dirfd, pmu);
9921001
pmu->events_table = perf_pmu__find_events_table(pmu);
993-
pmu_add_cpu_aliases(pmu);
9941002
pmu_add_sys_aliases(pmu);
9951003
list_add_tail(&pmu->list, pmus);
9961004

@@ -1368,6 +1376,7 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
13681376
static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
13691377
struct parse_events_term *term)
13701378
{
1379+
struct perf_pmu_alias *alias;
13711380
char *name;
13721381

13731382
if (parse_events__is_hardcoded_term(term))
@@ -1388,7 +1397,18 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
13881397
return NULL;
13891398
}
13901399

1391-
return perf_pmu__find_alias(pmu, name);
1400+
alias = perf_pmu__find_alias(pmu, name);
1401+
if (alias || pmu->cpu_aliases_added)
1402+
return alias;
1403+
1404+
/* Alias doesn't exist, try to get it from the json events. */
1405+
if (pmu->events_table &&
1406+
pmu_events_table__find_event(pmu->events_table, pmu, name,
1407+
pmu_add_cpu_aliases_map_callback,
1408+
pmu) == 0) {
1409+
alias = perf_pmu__find_alias(pmu, name);
1410+
}
1411+
return alias;
13921412
}
13931413

13941414

@@ -1555,18 +1575,23 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu)
15551575
return !pmu->is_core || perf_pmus__num_core_pmus() == 1;
15561576
}
15571577

1558-
bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name)
1578+
bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
15591579
{
1560-
return perf_pmu__find_alias(pmu, name) != NULL;
1580+
if (perf_pmu__find_alias(pmu, name) != NULL)
1581+
return true;
1582+
if (pmu->cpu_aliases_added || !pmu->events_table)
1583+
return false;
1584+
return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0;
15611585
}
15621586

1563-
size_t perf_pmu__num_events(const struct perf_pmu *pmu)
1587+
size_t perf_pmu__num_events(struct perf_pmu *pmu)
15641588
{
1565-
struct list_head *list;
1566-
size_t nr = 0;
1589+
size_t nr = pmu->sysfs_aliases;
15671590

1568-
list_for_each(list, &pmu->aliases)
1569-
nr++;
1591+
if (pmu->cpu_aliases_added)
1592+
nr += pmu->loaded_json_aliases;
1593+
else if (pmu->events_table)
1594+
nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases;
15701595

15711596
return pmu->selectable ? nr + 1 : nr;
15721597
}
@@ -1604,7 +1629,7 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,
16041629
return buf;
16051630
}
16061631

1607-
int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb)
1632+
int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb)
16081633
{
16091634
char buf[1024];
16101635
struct perf_pmu_alias *event;
@@ -1613,6 +1638,7 @@ int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_
16131638
};
16141639
int ret = 0;
16151640

1641+
pmu_add_cpu_aliases(pmu);
16161642
list_for_each_entry(event, &pmu->aliases, list) {
16171643
size_t buf_used;
16181644

tools/perf/util/pmu.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ struct perf_pmu {
118118
* @events_table: The events table for json events in pmu-events.c.
119119
*/
120120
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;
121130
/** @caps_initialized: Has the list caps been initialized? */
122131
bool caps_initialized;
123132
/** @nr_caps: The length of the list caps. */
@@ -199,9 +208,9 @@ bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
199208
bool is_pmu_core(const char *name);
200209
bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);
201210
bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu);
202-
bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name);
203-
size_t perf_pmu__num_events(const struct perf_pmu *pmu);
204-
int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb);
211+
bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name);
212+
size_t perf_pmu__num_events(struct perf_pmu *pmu);
213+
int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb);
205214
bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name);
206215

207216
/**

0 commit comments

Comments
 (0)