perf jevents: Add python type annotations

Make mypy clean.

Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Ian Rogers 2026-07-06 20:40:18 -07:00 committed by Namhyung Kim
parent e68dc36f8b
commit cda907c2c3

View File

@ -14,27 +14,27 @@ import collections
# Global command line arguments.
_args = None
# List of regular event tables.
_event_tables = []
_event_tables: list[str] = []
# List of event tables generated from "/sys" directories.
_sys_event_tables = []
_sys_event_tables: list[str] = []
# List of regular metric tables.
_metric_tables = []
_metric_tables: list[str] = []
# List of metric tables generated from "/sys" directories.
_sys_metric_tables = []
_sys_metric_tables: list[str] = []
# Mapping between sys event table names and sys metric table names.
_sys_event_table_to_metric_table_mapping = {}
# Map from an event name to an architecture standard
# JsonEvent. Architecture standard events are in json files in the top
# f'{_args.starting_dir}/{_args.arch}' directory.
_arch_std_events = {}
_arch_std_events: Dict[str, "JsonEvent"] = {}
# Events to write out when the table is closed
_pending_events = []
_pending_events: list["JsonEvent"] = []
# Name of events table to be written out
_pending_events_tblname = None
_pending_events_tblname: Optional[str] = None
# Metrics to write out when the table is closed
_pending_metrics = []
_pending_metrics: list["JsonEvent"] = []
# Name of metrics table to be written out
_pending_metrics_tblname = None
_pending_metrics_tblname: Optional[str] = None
# Global BigCString shared by all structures.
_bcs = None
# Map from the name of a metric group to a description of the group.
@ -210,7 +210,7 @@ class JsonEvent:
"""Convert an int to a string similar to a printf modifier of %#llx."""
return str(x) if x >= 0 and x < 10 else hex(x)
def fixdesc(s: str) -> str:
def fixdesc(s: Optional[str]) -> Optional[str]:
"""Fix formatting issue for the desc string."""
if s is None:
return None
@ -218,7 +218,7 @@ class JsonEvent:
'. '), '.').replace('\n', '\\n').replace(
'\"', '\\"').replace('\r', '\\r')
def convert_aggr_mode(aggr_mode: str) -> Optional[str]:
def convert_aggr_mode(aggr_mode: Optional[str]) -> Optional[str]:
"""Returns the aggr_mode_class enum value associated with the JSON string."""
if not aggr_mode:
return None
@ -228,7 +228,7 @@ class JsonEvent:
}
return aggr_mode_to_enum[aggr_mode]
def convert_metric_constraint(metric_constraint: str) -> Optional[str]:
def convert_metric_constraint(metric_constraint: Optional[str]) -> Optional[str]:
"""Returns the metric_event_groups enum value associated with the JSON string."""
if not metric_constraint:
return None
@ -241,7 +241,7 @@ class JsonEvent:
}
return metric_constraint_to_enum[metric_constraint]
def lookup_msr(num: str) -> Optional[str]:
def lookup_msr(num: Optional[str]) -> Optional[str]:
"""Converts the msr number, or first in a list to the appropriate event field."""
if not num:
return None
@ -257,7 +257,7 @@ class JsonEvent:
}
return msrmap[int(num.split(',', 1)[0], 0)]
def real_event(name: str, event: str) -> Optional[str]:
def real_event(name: Optional[str], event: Optional[str]) -> Optional[str]:
"""Convert well known event names to an event string otherwise use the event argument."""
fixed = {
'inst_retired.any': 'event=0xc0,period=2000003',
@ -273,7 +273,7 @@ class JsonEvent:
return fixed[name.lower()]
return event
def unit_to_pmu(unit: str) -> Optional[str]:
def unit_to_pmu(unit: Optional[str]) -> Optional[str]:
"""Convert a JSON Unit to Linux PMU name."""
if not unit:
return 'default_core'
@ -308,21 +308,21 @@ class JsonEvent:
return table[unit] if unit in table else f'uncore_{unit.lower()}'
def is_zero(val: str) -> bool:
try:
if val.startswith('0x'):
return int(val, 16) == 0
else:
return int(val) == 0
except e:
return False
try:
if val.startswith('0x'):
return int(val, 16) == 0
else:
return int(val) == 0
except:
return False
def canonicalize_value(val: str) -> str:
try:
if val.startswith('0x'):
return llx(int(val, 16))
return str(int(val))
except e:
return val
try:
if val.startswith('0x'):
return llx(int(val, 16))
return str(int(val))
except:
return val
eventcode = 0
if 'EventCode' in jd:
@ -374,7 +374,8 @@ class JsonEvent:
if precise and self.desc and '(Precise Event)' not in self.desc:
extra_desc += ' (Must be precise)' if precise == '2' else (' (Precise '
'event)')
event = None
self.event: Optional[str] = None
event: Optional[str] = None
if configcode is not None:
event = f'config={llx(configcode)}'
elif eventidcode is not None:
@ -459,6 +460,7 @@ class JsonEvent:
return f'\t/* {s} */\n' if len(s) < 80 else f'\t/* {s[0:80]}... */\n'
s = self.build_c_string(metric)
assert _bcs is not None
return f'{make_comment(s)}\t{{ { _bcs.offsets[s] } }},\n'
@ -528,6 +530,7 @@ def print_pending_events() -> None:
return
global _pending_events_tblname
assert _pending_events_tblname is not None
if _pending_events_tblname.endswith('_sys'):
global _sys_event_tables
_sys_event_tables.append(_pending_events_tblname)
@ -538,7 +541,8 @@ def print_pending_events() -> None:
first = True
last_pmu = None
last_name = None
pmus = set()
pmus: Set[Tuple[str, str]] = set()
assert _args is not None
for event in sorted(_pending_events, key=event_cmp_key):
if last_pmu and last_pmu == event.pmu:
assert event.name != last_name, f"Duplicate event: {last_pmu}/{last_name}/ in {_pending_events_tblname}"
@ -580,6 +584,7 @@ def print_pending_metrics() -> None:
return ''
return s
assert j.metric_expr is not None
return (fix_none(j.pmu), fix_none(j.metric_name), j.metric_expr.ToPerfJson(),
fix_none(j.desc))
@ -588,6 +593,7 @@ def print_pending_metrics() -> None:
return
global _pending_metrics_tblname
assert _pending_metrics_tblname is not None
if _pending_metrics_tblname.endswith('_sys'):
global _sys_metric_tables
_sys_metric_tables.append(_pending_metrics_tblname)
@ -597,7 +603,8 @@ def print_pending_metrics() -> None:
first = True
last_pmu = None
pmus = set()
pmus: Set[Tuple[str, str]] = set()
assert _args is not None
for metric in sorted(_pending_metrics, key=metric_cmp_key):
if metric.pmu != last_pmu:
if not first:
@ -633,7 +640,6 @@ def get_topic(topic: str) -> str:
return removesuffix(topic, '.json').replace('-', ' ')
def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
if item.is_dir():
return
@ -647,6 +653,7 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
if not item.is_file() or not item.name.endswith('.json'):
return
assert _bcs is not None
if item.name.endswith('metricgroups.json'):
metricgroup_descriptions = json.load(open(item.path))
for mgroup in metricgroup_descriptions:
@ -708,6 +715,7 @@ def process_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
def print_mapping_table(archs: Sequence[str]) -> None:
"""Read the mapfile and generate the struct from cpuid string to event table."""
assert _args is not None
_args.output_file.write("""
/* Struct used to make the PMU event table implementation opaque to callers. */
struct pmu_events_table {
@ -825,6 +833,7 @@ static const struct pmu_events_map pmu_events_map[] = {
def print_metric_table_functions() -> None:
assert _args is not None
_args.output_file.write("""
const char *pmu_metrics_table__name(const struct pmu_metrics_table *table)
{
@ -868,6 +877,7 @@ int pmu_metrics_table__iterate_tables(pmu_metrics_table_iter_t fn, void *data)
def print_system_mapping_table() -> None:
assert _args is not None
"""C struct mapping table array for tables from /sys directories."""
_args.output_file.write("""
struct pmu_sys_events {
@ -1404,6 +1414,7 @@ int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data)
""")
def print_metricgroups() -> None:
assert _args is not None
_args.output_file.write("""
static const int metricgroups[][2] = {
""")
@ -1447,6 +1458,7 @@ def main() -> None:
def ftw(path: str, parents: Sequence[str],
action: Callable[[Sequence[str], os.DirEntry], None]) -> None:
"""Replicate the directory/file walking behavior of C's file tree walk."""
assert _args is not None
for item in sorted(os.scandir(path), key=lambda e: e.name):
if _args.model != 'all' and item.is_dir():
# Check if the model matches one in _args.model.
@ -1517,6 +1529,7 @@ struct pmu_table_entry {
preprocess_arch_std_files(arch_path)
ftw(arch_path, [], preprocess_one_file)
assert _bcs is not None
_bcs.compute()
_args.output_file.write('/* clang-format off */\n')
if not _args.output_string_file: