mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-14 15:54:15 +08:00
perf jevents: Group events by PMU
Prior to this change a cpuid would map to a list of events where the PMU would be encoded alongside the event information. This change breaks apart each group of events so that there is a group per PMU. A new table is added with the PMU's name and the list of events, the original table now holding an array of these per PMU tables. These changes are to make it easier to get per PMU information about events, rather than the current approach of scanning all events. The perf binary size with BPF skeletons on x86 is reduced by about 1%. The unidentified PMU is now always expanded to "cpu". 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-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
4000519eb0
commit
2e255b4f9f
@ -42,7 +42,7 @@ _metricgroups = {}
|
||||
# Order specific JsonEvent attributes will be visited.
|
||||
_json_event_attributes = [
|
||||
# cmp_sevent related attributes.
|
||||
'name', 'pmu', 'topic', 'desc',
|
||||
'name', 'topic', 'desc',
|
||||
# Seems useful, put it early.
|
||||
'event',
|
||||
# Short things in alphabetical order.
|
||||
@ -53,7 +53,7 @@ _json_event_attributes = [
|
||||
|
||||
# Attributes that are in pmu_metric rather than pmu_event.
|
||||
_json_metric_attributes = [
|
||||
'pmu', 'metric_name', 'metric_group', 'metric_expr', 'metric_threshold',
|
||||
'metric_name', 'metric_group', 'metric_expr', 'metric_threshold',
|
||||
'desc', 'long_desc', 'unit', 'compat', 'metricgroup_no_group',
|
||||
'default_metricgroup_name', 'aggr_mode', 'event_grouping'
|
||||
]
|
||||
@ -252,7 +252,7 @@ class JsonEvent:
|
||||
def unit_to_pmu(unit: str) -> Optional[str]:
|
||||
"""Convert a JSON Unit to Linux PMU name."""
|
||||
if not unit:
|
||||
return None
|
||||
return 'cpu'
|
||||
# Comment brought over from jevents.c:
|
||||
# it's not realistic to keep adding these, we need something more scalable ...
|
||||
table = {
|
||||
@ -343,10 +343,13 @@ class JsonEvent:
|
||||
self.desc += extra_desc
|
||||
if self.long_desc and extra_desc:
|
||||
self.long_desc += extra_desc
|
||||
if self.pmu:
|
||||
if self.desc and not self.desc.endswith('. '):
|
||||
if self.pmu and self.pmu != 'cpu':
|
||||
if not self.desc:
|
||||
self.desc = 'Unit: ' + self.pmu
|
||||
else:
|
||||
if not self.desc.endswith('. '):
|
||||
self.desc += '. '
|
||||
self.desc = (self.desc if self.desc else '') + ('Unit: ' + self.pmu + ' ')
|
||||
self.desc += 'Unit: ' + self.pmu
|
||||
if arch_std:
|
||||
if arch_std.lower() in _arch_std_events:
|
||||
event = _arch_std_events[arch_std.lower()].event
|
||||
@ -437,13 +440,13 @@ def add_events_table_entries(item: os.DirEntry, topic: str) -> None:
|
||||
def print_pending_events() -> None:
|
||||
"""Optionally close events table."""
|
||||
|
||||
def event_cmp_key(j: JsonEvent) -> Tuple[bool, str, str, str, str]:
|
||||
def event_cmp_key(j: JsonEvent) -> Tuple[str, str, bool, str, str]:
|
||||
def fix_none(s: Optional[str]) -> str:
|
||||
if s is None:
|
||||
return ''
|
||||
return s
|
||||
|
||||
return (j.desc is not None, fix_none(j.topic), fix_none(j.name), fix_none(j.pmu),
|
||||
return (fix_none(j.pmu).replace(',','_'), fix_none(j.name), j.desc is not None, fix_none(j.topic),
|
||||
fix_none(j.metric_name))
|
||||
|
||||
global _pending_events
|
||||
@ -458,13 +461,36 @@ def print_pending_events() -> None:
|
||||
global event_tables
|
||||
_event_tables.append(_pending_events_tblname)
|
||||
|
||||
_args.output_file.write(
|
||||
f'static const struct compact_pmu_event {_pending_events_tblname}[] = {{\n')
|
||||
|
||||
first = True
|
||||
last_pmu = None
|
||||
pmus = set()
|
||||
for event in sorted(_pending_events, key=event_cmp_key):
|
||||
if event.pmu != last_pmu:
|
||||
if not first:
|
||||
_args.output_file.write('};\n')
|
||||
pmu_name = event.pmu.replace(',', '_')
|
||||
_args.output_file.write(
|
||||
f'static const struct compact_pmu_event {_pending_events_tblname}_{pmu_name}[] = {{\n')
|
||||
first = False
|
||||
last_pmu = event.pmu
|
||||
pmus.add((event.pmu, pmu_name))
|
||||
|
||||
_args.output_file.write(event.to_c_string(metric=False))
|
||||
_pending_events = []
|
||||
|
||||
_args.output_file.write(f"""
|
||||
}};
|
||||
|
||||
const struct pmu_table_entry {_pending_events_tblname}[] = {{
|
||||
""")
|
||||
for (pmu, tbl_pmu) in sorted(pmus):
|
||||
pmu_name = f"{pmu}\\000"
|
||||
_args.output_file.write(f"""{{
|
||||
.entries = {_pending_events_tblname}_{tbl_pmu},
|
||||
.num_entries = ARRAY_SIZE({_pending_events_tblname}_{tbl_pmu}),
|
||||
.pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }},
|
||||
}},
|
||||
""")
|
||||
_args.output_file.write('};\n\n')
|
||||
|
||||
def print_pending_metrics() -> None:
|
||||
@ -490,13 +516,36 @@ def print_pending_metrics() -> None:
|
||||
global metric_tables
|
||||
_metric_tables.append(_pending_metrics_tblname)
|
||||
|
||||
_args.output_file.write(
|
||||
f'static const struct compact_pmu_event {_pending_metrics_tblname}[] = {{\n')
|
||||
|
||||
first = True
|
||||
last_pmu = None
|
||||
pmus = set()
|
||||
for metric in sorted(_pending_metrics, key=metric_cmp_key):
|
||||
if metric.pmu != last_pmu:
|
||||
if not first:
|
||||
_args.output_file.write('};\n')
|
||||
pmu_name = metric.pmu.replace(',', '_')
|
||||
_args.output_file.write(
|
||||
f'static const struct compact_pmu_event {_pending_metrics_tblname}_{pmu_name}[] = {{\n')
|
||||
first = False
|
||||
last_pmu = metric.pmu
|
||||
pmus.add((metric.pmu, pmu_name))
|
||||
|
||||
_args.output_file.write(metric.to_c_string(metric=True))
|
||||
_pending_metrics = []
|
||||
|
||||
_args.output_file.write(f"""
|
||||
}};
|
||||
|
||||
const struct pmu_table_entry {_pending_metrics_tblname}[] = {{
|
||||
""")
|
||||
for (pmu, tbl_pmu) in sorted(pmus):
|
||||
pmu_name = f"{pmu}\\000"
|
||||
_args.output_file.write(f"""{{
|
||||
.entries = {_pending_metrics_tblname}_{tbl_pmu},
|
||||
.num_entries = ARRAY_SIZE({_pending_metrics_tblname}_{tbl_pmu}),
|
||||
.pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }},
|
||||
}},
|
||||
""")
|
||||
_args.output_file.write('};\n\n')
|
||||
|
||||
def get_topic(topic: str) -> str:
|
||||
@ -532,6 +581,8 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
|
||||
|
||||
topic = get_topic(item.name)
|
||||
for event in read_json_events(item.path, topic):
|
||||
pmu_name = f"{event.pmu}\\000"
|
||||
_bcs.add(pmu_name)
|
||||
if event.name:
|
||||
_bcs.add(event.build_c_string(metric=False))
|
||||
if event.metric_name:
|
||||
@ -577,14 +628,14 @@ def print_mapping_table(archs: Sequence[str]) -> None:
|
||||
_args.output_file.write("""
|
||||
/* Struct used to make the PMU event table implementation opaque to callers. */
|
||||
struct pmu_events_table {
|
||||
const struct compact_pmu_event *entries;
|
||||
size_t length;
|
||||
const struct pmu_table_entry *pmus;
|
||||
uint32_t num_pmus;
|
||||
};
|
||||
|
||||
/* Struct used to make the PMU metric table implementation opaque to callers. */
|
||||
struct pmu_metrics_table {
|
||||
const struct compact_pmu_event *entries;
|
||||
size_t length;
|
||||
const struct pmu_table_entry *pmus;
|
||||
uint32_t num_pmus;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -614,12 +665,12 @@ const struct pmu_events_map pmu_events_map[] = {
|
||||
\t.arch = "testarch",
|
||||
\t.cpuid = "testcpu",
|
||||
\t.event_table = {
|
||||
\t\t.entries = pmu_events__test_soc_cpu,
|
||||
\t\t.length = ARRAY_SIZE(pmu_events__test_soc_cpu),
|
||||
\t\t.pmus = pmu_events__test_soc_cpu,
|
||||
\t\t.num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu),
|
||||
\t},
|
||||
\t.metric_table = {
|
||||
\t\t.entries = pmu_metrics__test_soc_cpu,
|
||||
\t\t.length = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
|
||||
\t\t.pmus = pmu_metrics__test_soc_cpu,
|
||||
\t\t.num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
|
||||
\t}
|
||||
},
|
||||
""")
|
||||
@ -649,12 +700,12 @@ const struct pmu_events_map pmu_events_map[] = {
|
||||
\t.arch = "{arch}",
|
||||
\t.cpuid = "{cpuid}",
|
||||
\t.event_table = {{
|
||||
\t\t.entries = {event_tblname},
|
||||
\t\t.length = {event_size}
|
||||
\t\t.pmus = {event_tblname},
|
||||
\t\t.num_pmus = {event_size}
|
||||
\t}},
|
||||
\t.metric_table = {{
|
||||
\t\t.entries = {metric_tblname},
|
||||
\t\t.length = {metric_size}
|
||||
\t\t.pmus = {metric_tblname},
|
||||
\t\t.num_pmus = {metric_size}
|
||||
\t}}
|
||||
}},
|
||||
""")
|
||||
@ -685,15 +736,15 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = {
|
||||
for tblname in _sys_event_tables:
|
||||
_args.output_file.write(f"""\t{{
|
||||
\t\t.event_table = {{
|
||||
\t\t\t.entries = {tblname},
|
||||
\t\t\t.length = ARRAY_SIZE({tblname})
|
||||
\t\t\t.pmus = {tblname},
|
||||
\t\t\t.num_pmus = ARRAY_SIZE({tblname})
|
||||
\t\t}},""")
|
||||
metric_tblname = _sys_event_table_to_metric_table_mapping[tblname]
|
||||
if metric_tblname in _sys_metric_tables:
|
||||
_args.output_file.write(f"""
|
||||
\t\t.metric_table = {{
|
||||
\t\t\t.entries = {metric_tblname},
|
||||
\t\t\t.length = ARRAY_SIZE({metric_tblname})
|
||||
\t\t\t.pmus = {metric_tblname},
|
||||
\t\t\t.num_pmus = ARRAY_SIZE({metric_tblname})
|
||||
\t\t}},""")
|
||||
printed_metric_tables.append(metric_tblname)
|
||||
_args.output_file.write(f"""
|
||||
@ -753,18 +804,56 @@ static void decompress_metric(int offset, struct pmu_metric *pm)
|
||||
_args.output_file.write('\twhile (*p++);')
|
||||
_args.output_file.write("""}
|
||||
|
||||
static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table,
|
||||
const struct pmu_table_entry *pmu,
|
||||
pmu_event_iter_fn fn,
|
||||
void *data)
|
||||
{
|
||||
int ret;
|
||||
struct pmu_event pe = {
|
||||
.pmu = &big_c_string[pmu->pmu_name.offset],
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < pmu->num_entries; i++) {
|
||||
decompress_event(pmu->entries[i].offset, &pe);
|
||||
if (!pe.name)
|
||||
continue;
|
||||
ret = fn(&pe, table, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pmu_events_table__for_each_event(const struct pmu_events_table *table,
|
||||
pmu_event_iter_fn fn,
|
||||
void *data)
|
||||
{
|
||||
for (size_t i = 0; i < table->length; i++) {
|
||||
struct pmu_event pe;
|
||||
int ret;
|
||||
for (size_t i = 0; i < table->num_pmus; i++) {
|
||||
int ret = pmu_events_table__for_each_event_pmu(table, &table->pmus[i],
|
||||
fn, data);
|
||||
|
||||
decompress_event(table->entries[i].offset, &pe);
|
||||
if (!pe.name)
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
|
||||
const struct pmu_table_entry *pmu,
|
||||
pmu_metric_iter_fn fn,
|
||||
void *data)
|
||||
{
|
||||
int ret;
|
||||
struct pmu_metric pm = {
|
||||
.pmu = &big_c_string[pmu->pmu_name.offset],
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < pmu->num_entries; i++) {
|
||||
decompress_metric(pmu->entries[i].offset, &pm);
|
||||
if (!pm.metric_expr)
|
||||
continue;
|
||||
ret = fn(&pe, table, data);
|
||||
ret = fn(&pm, table, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -775,14 +864,10 @@ int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
|
||||
pmu_metric_iter_fn fn,
|
||||
void *data)
|
||||
{
|
||||
for (size_t i = 0; i < table->length; i++) {
|
||||
struct pmu_metric pm;
|
||||
int ret;
|
||||
for (size_t i = 0; i < table->num_pmus; i++) {
|
||||
int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i],
|
||||
fn, data);
|
||||
|
||||
decompress_metric(table->entries[i].offset, &pm);
|
||||
if (!pm.metric_expr)
|
||||
continue;
|
||||
ret = fn(&pm, table, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -1013,6 +1098,12 @@ struct compact_pmu_event {
|
||||
int offset;
|
||||
};
|
||||
|
||||
struct pmu_table_entry {
|
||||
const struct compact_pmu_event *entries;
|
||||
uint32_t num_entries;
|
||||
struct compact_pmu_event pmu_name;
|
||||
};
|
||||
|
||||
""")
|
||||
archs = []
|
||||
for item in os.scandir(_args.starting_dir):
|
||||
|
@ -44,6 +44,7 @@ struct perf_pmu_test_pmu {
|
||||
|
||||
static const struct perf_pmu_test_event bp_l1_btb_correct = {
|
||||
.event = {
|
||||
.pmu = "cpu",
|
||||
.name = "bp_l1_btb_correct",
|
||||
.event = "event=0x8a",
|
||||
.desc = "L1 BTB Correction",
|
||||
@ -55,6 +56,7 @@ static const struct perf_pmu_test_event bp_l1_btb_correct = {
|
||||
|
||||
static const struct perf_pmu_test_event bp_l2_btb_correct = {
|
||||
.event = {
|
||||
.pmu = "cpu",
|
||||
.name = "bp_l2_btb_correct",
|
||||
.event = "event=0x8b",
|
||||
.desc = "L2 BTB Correction",
|
||||
@ -66,6 +68,7 @@ static const struct perf_pmu_test_event bp_l2_btb_correct = {
|
||||
|
||||
static const struct perf_pmu_test_event segment_reg_loads_any = {
|
||||
.event = {
|
||||
.pmu = "cpu",
|
||||
.name = "segment_reg_loads.any",
|
||||
.event = "event=0x6,period=200000,umask=0x80",
|
||||
.desc = "Number of segment register loads",
|
||||
@ -77,6 +80,7 @@ static const struct perf_pmu_test_event segment_reg_loads_any = {
|
||||
|
||||
static const struct perf_pmu_test_event dispatch_blocked_any = {
|
||||
.event = {
|
||||
.pmu = "cpu",
|
||||
.name = "dispatch_blocked.any",
|
||||
.event = "event=0x9,period=200000,umask=0x20",
|
||||
.desc = "Memory cluster signals to block micro-op dispatch for any reason",
|
||||
@ -88,6 +92,7 @@ static const struct perf_pmu_test_event dispatch_blocked_any = {
|
||||
|
||||
static const struct perf_pmu_test_event eist_trans = {
|
||||
.event = {
|
||||
.pmu = "cpu",
|
||||
.name = "eist_trans",
|
||||
.event = "event=0x3a,period=200000,umask=0x0",
|
||||
.desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
|
||||
@ -99,6 +104,7 @@ static const struct perf_pmu_test_event eist_trans = {
|
||||
|
||||
static const struct perf_pmu_test_event l3_cache_rd = {
|
||||
.event = {
|
||||
.pmu = "cpu",
|
||||
.name = "l3_cache_rd",
|
||||
.event = "event=0x40",
|
||||
.desc = "L3 cache access, read",
|
||||
@ -403,7 +409,7 @@ static int test__pmu_event_table_core_callback(const struct pmu_event *pe,
|
||||
struct perf_pmu_test_event const **test_event_table;
|
||||
bool found = false;
|
||||
|
||||
if (pe->pmu)
|
||||
if (strcmp(pe->pmu, "cpu"))
|
||||
test_event_table = &uncore_events[0];
|
||||
else
|
||||
test_event_table = &core_events[0];
|
||||
|
Loading…
Reference in New Issue
Block a user