mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
perf pmu-events: Clean up mypy and pylint issues
Clean up mypy type errors and pylint warnings across the pmu-events Python scripts (amd_metrics.py, intel_metrics.py, jevents.py, make_legacy_cache.py, and metric.py) in preparation for making MYPY and PYLINT build tests opt-out. In addition to type annotations and unused import/variable cleanups, fix three bugs in intel_metrics.py exposed by static analysis: - Fix references to undefined 'args.model' (instead of '_args.model') inside try/except blocks in IntelL2() and UncoreMemBw(), which previously threw NameError and silently disabled Skylake/CascadeLake L2 silent eviction adjustments and uncore memory bandwidth JSON loading. - Define DC_WB_U and DC_WB_D before their first use in IntelL2(), fixing an UnboundLocalError that silently dropped the l2_out_rate, wbn, and isd metrics. - Fix Event-to-string comparison and addition in IntelFp() by comparing and modifying 'f_assist.name' instead of the Event object 'f_assist'. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
ca23ecf8ee
commit
db5a607501
|
|
@ -3,7 +3,7 @@
|
|||
import argparse
|
||||
import math
|
||||
import os
|
||||
from typing import Optional
|
||||
from typing import Optional, Union
|
||||
from common_metrics import Cycles
|
||||
from metric import (d_ratio, has_event, max, Event, JsonEncodeMetric,
|
||||
JsonEncodeMetricGroupDescriptions, Literal, LoadEvents,
|
||||
|
|
@ -70,7 +70,6 @@ def AmdBr():
|
|||
])
|
||||
|
||||
def Conditional() -> Optional[MetricGroup]:
|
||||
global _zen_model
|
||||
br = Event("ex_ret_brn_cond", "ex_ret_cond")
|
||||
br_r = d_ratio(br, interval_sec)
|
||||
ins_r = d_ratio(ins, br)
|
||||
|
|
@ -156,25 +155,24 @@ def AmdCtxSw() -> MetricGroup:
|
|||
|
||||
|
||||
def AmdDtlb() -> Optional[MetricGroup]:
|
||||
global _zen_model
|
||||
if _zen_model >= 4:
|
||||
return None
|
||||
|
||||
d_dat = Event("ls_dc_accesses") if _zen_model <= 3 else None
|
||||
d_dat = Event("ls_dc_accesses")
|
||||
d_h4k = Event("ls_l1_d_tlb_miss.tlb_reload_4k_l2_hit")
|
||||
d_hcoal = Event(
|
||||
d_hcoal: Union[Event, int] = Event(
|
||||
"ls_l1_d_tlb_miss.tlb_reload_coalesced_page_hit") if _zen_model >= 2 else 0
|
||||
d_h2m = Event("ls_l1_d_tlb_miss.tlb_reload_2m_l2_hit")
|
||||
d_h1g = Event("ls_l1_d_tlb_miss.tlb_reload_1g_l2_hit")
|
||||
|
||||
d_m4k = Event("ls_l1_d_tlb_miss.tlb_reload_4k_l2_miss")
|
||||
d_mcoal = Event(
|
||||
d_mcoal: Union[Event, int] = Event(
|
||||
"ls_l1_d_tlb_miss.tlb_reload_coalesced_page_miss") if _zen_model >= 2 else 0
|
||||
d_m2m = Event("ls_l1_d_tlb_miss.tlb_reload_2m_l2_miss")
|
||||
d_m1g = Event("ls_l1_d_tlb_miss.tlb_reload_1g_l2_miss")
|
||||
|
||||
d_w0 = Event("ls_tablewalker.dc_type0") if _zen_model <= 3 else None
|
||||
d_w1 = Event("ls_tablewalker.dc_type1") if _zen_model <= 3 else None
|
||||
d_w0 = Event("ls_tablewalker.dc_type0")
|
||||
d_w1 = Event("ls_tablewalker.dc_type1")
|
||||
walks = d_w0 + d_w1
|
||||
walks_r = d_ratio(walks, interval_sec)
|
||||
ins_w = d_ratio(ins, walks)
|
||||
|
|
@ -266,7 +264,6 @@ def AmdDtlb() -> Optional[MetricGroup]:
|
|||
|
||||
|
||||
def AmdIotlb() -> Optional[MetricGroup]:
|
||||
global _zen_model
|
||||
if _zen_model < 2:
|
||||
return None
|
||||
|
||||
|
|
@ -322,7 +319,6 @@ def AmdIotlb() -> Optional[MetricGroup]:
|
|||
|
||||
|
||||
def AmdItlb():
|
||||
global _zen_model
|
||||
l2h = Event("bp_l1_tlb_miss_l2_tlb_hit", "bp_l1_tlb_miss_l2_hit")
|
||||
l2m = Event("bp_l1_tlb_miss_l2_tlb_miss.all", "l2_itlb_misses",)
|
||||
l2r = l2h + l2m
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ import json
|
|||
import math
|
||||
import os
|
||||
import re
|
||||
from typing import Optional
|
||||
from typing import Optional, Union
|
||||
from common_metrics import Cycles
|
||||
from metric import (d_ratio, has_event, max, aggr_nr, CheckPmu, Event,
|
||||
JsonEncodeMetric, JsonEncodeMetricGroupDescriptions,
|
||||
from metric import (d_ratio, has_event, max, aggr_nr, CheckPmu, Constant, Event,
|
||||
Expression, JsonEncodeMetric, JsonEncodeMetricGroupDescriptions,
|
||||
Literal, LoadEvents, Metric, MetricConstraint, MetricGroup,
|
||||
MetricRef, Select)
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ def Tsx() -> Optional[MetricGroup]:
|
|||
# sysfs version so that we can detect its presence at runtime.
|
||||
transaction_start = Event("RTM_RETIRED.START")
|
||||
transaction_start = Event(f'{pmu}/tx\\-start/')
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
elision_start = None
|
||||
|
|
@ -100,7 +100,7 @@ def Tsx() -> Optional[MetricGroup]:
|
|||
# case. Again, prefer the sysfs encoding of the event.
|
||||
elision_start = Event("HLE_RETIRED.START")
|
||||
elision_start = Event(f'{pmu}/el\\-start/')
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return MetricGroup('transaction', [
|
||||
|
|
@ -139,7 +139,7 @@ def IntelBr():
|
|||
br_clr = None
|
||||
try:
|
||||
br_clr = Event("BACLEARS.ANY", "BACLEARS.ALL")
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
br_r = d_ratio(br_all, interval_sec)
|
||||
|
|
@ -171,7 +171,7 @@ def IntelBr():
|
|||
br_m_tk = Event("BR_MISP_RETIRED.NEAR_TAKEN",
|
||||
"BR_MISP_RETIRED.TAKEN_JCC",
|
||||
"BR_INST_RETIRED.MISPRED_TAKEN")
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
br_r = d_ratio(br_all, interval_sec)
|
||||
ins_r = d_ratio(ins, br_all)
|
||||
|
|
@ -199,7 +199,7 @@ def IntelBr():
|
|||
br_m_cond = Event("BR_MISP_RETIRED.COND",
|
||||
"BR_MISP_RETIRED.CONDITIONAL",
|
||||
"BR_MISP_RETIRED.TAKEN_JCC")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
br_cond_nt = None
|
||||
|
|
@ -207,7 +207,7 @@ def IntelBr():
|
|||
try:
|
||||
br_cond_nt = Event("BR_INST_RETIRED.COND_NTAKEN")
|
||||
br_m_cond_nt = Event("BR_MISP_RETIRED.COND_NTAKEN")
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
br_r = d_ratio(br_cond, interval_sec)
|
||||
ins_r = d_ratio(ins, br_cond)
|
||||
|
|
@ -222,7 +222,7 @@ def IntelBr():
|
|||
"Retired conditional branch instructions mispredicted as a "
|
||||
"percentage of all conditional branches.", misp_r, "100%"),
|
||||
]
|
||||
if not br_m_cond_nt:
|
||||
if not br_m_cond_nt or not br_cond_nt:
|
||||
return MetricGroup("lpm_br_cond", taken_metrics)
|
||||
|
||||
br_r = d_ratio(br_cond_nt, interval_sec)
|
||||
|
|
@ -247,7 +247,7 @@ def IntelBr():
|
|||
def Far() -> Optional[MetricGroup]:
|
||||
try:
|
||||
br_far = Event("BR_INST_RETIRED.FAR_BRANCH")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
br_r = d_ratio(br_far, interval_sec)
|
||||
|
|
@ -284,7 +284,7 @@ def IntelCtxSw() -> MetricGroup:
|
|||
ev = Event("MEM_INST_RETIRED.ALL_LOADS", "MEM_UOPS_RETIRED.ALL_LOADS")
|
||||
metrics.append(Metric("lpm_cs_loads", "Loads per context switch",
|
||||
d_ratio(ev, cs), "loads/cs"))
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
|
|
@ -292,14 +292,14 @@ def IntelCtxSw() -> MetricGroup:
|
|||
"MEM_UOPS_RETIRED.ALL_STORES")
|
||||
metrics.append(Metric("lpm_cs_stores", "Stores per context switch",
|
||||
d_ratio(ev, cs), "stores/cs"))
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
ev = Event("BR_INST_RETIRED.NEAR_TAKEN", "BR_INST_RETIRED.TAKEN_JCC")
|
||||
metrics.append(Metric("lpm_cs_br_taken", "Branches taken per context switch",
|
||||
d_ratio(ev, cs), "br_taken/cs"))
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
|
|
@ -309,12 +309,12 @@ def IntelCtxSw() -> MetricGroup:
|
|||
try:
|
||||
l2_misses += Event("L2_RQSTS.HWPF_MISS",
|
||||
"L2_RQSTS.L2_PF_MISS", "L2_RQSTS.PF_MISS")
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
metrics.append(Metric("lpm_cs_l2_misses", "L2 misses per context switch",
|
||||
d_ratio(l2_misses, cs), "l2_misses/cs"))
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return MetricGroup("lpm_cs", metrics,
|
||||
|
|
@ -327,7 +327,7 @@ def IntelFpu() -> Optional[MetricGroup]:
|
|||
try:
|
||||
s_64 = Event("FP_ARITH_INST_RETIRED.SCALAR_SINGLE",
|
||||
"SIMD_INST_RETIRED.SCALAR_SINGLE")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
d_64 = Event("FP_ARITH_INST_RETIRED.SCALAR_DOUBLE",
|
||||
"SIMD_INST_RETIRED.SCALAR_DOUBLE")
|
||||
|
|
@ -352,21 +352,21 @@ def IntelFpu() -> Optional[MetricGroup]:
|
|||
flop += 16 * s_512
|
||||
d_512 = Event("FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE")
|
||||
flop += 8 * d_512
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
f_assist = Event("ASSISTS.FP", "FP_ASSIST.ANY", "FP_ASSIST.S")
|
||||
if f_assist in [
|
||||
"ASSISTS.FP",
|
||||
"FP_ASSIST.S",
|
||||
]:
|
||||
f_assist += "/cmask=1/"
|
||||
|
||||
flop_r = d_ratio(flop, interval_sec)
|
||||
flop_c = d_ratio(flop, cyc)
|
||||
nmi_constraint = MetricConstraint.GROUPED_EVENTS
|
||||
if f_assist.name == "ASSISTS.FP": # Icelake+
|
||||
nmi_constraint = MetricConstraint.NO_GROUP_EVENTS_NMI
|
||||
if f_assist.name in [
|
||||
"ASSISTS.FP",
|
||||
"FP_ASSIST.S",
|
||||
]:
|
||||
f_assist = Event(f"{f_assist.name}/cmask=1/")
|
||||
|
||||
flop_r = d_ratio(flop, interval_sec)
|
||||
flop_c = d_ratio(flop, cyc)
|
||||
|
||||
def FpuMetrics(group: str, fl: Optional[Event], mult: int, desc: str) -> Optional[MetricGroup]:
|
||||
if not fl:
|
||||
|
|
@ -421,16 +421,17 @@ def IntelFpu() -> Optional[MetricGroup]:
|
|||
def IntelIlp() -> MetricGroup:
|
||||
tsc = Event("msr/tsc/")
|
||||
c0 = Event("msr/mperf/")
|
||||
low = tsc - c0
|
||||
low = max(tsc - c0, 0)
|
||||
inst_ret = Event("INST_RETIRED.ANY_P")
|
||||
inst_ret_c = [Event(f"{inst_ret.name}/cmask={x}/") for x in range(1, 6)]
|
||||
core_cycles = Event("CPU_CLK_UNHALTED.THREAD_P_ANY",
|
||||
"CPU_CLK_UNHALTED.DISTRIBUTED",
|
||||
"cycles")
|
||||
inst_ret_c = [Event(f"{inst_ret.name}/cmask={x}/") for x in range(1, 6)]
|
||||
|
||||
ilp = [d_ratio(max(inst_ret_c[x] - inst_ret_c[x + 1], 0), core_cycles)
|
||||
for x in range(0, 4)]
|
||||
ilp.append(d_ratio(inst_ret_c[4], core_cycles))
|
||||
ilp0 = 1
|
||||
ilp0: Expression = Constant(1)
|
||||
for x in ilp:
|
||||
ilp0 -= x
|
||||
return MetricGroup("lpm_ilp", [
|
||||
|
|
@ -465,7 +466,7 @@ def IntelIotlb() -> Optional[MetricGroup]:
|
|||
+ Event("UNC_IIO_IOMMU0.1G_HITS")
|
||||
)
|
||||
total_miss = Event("UNC_IIO_IOMMU0.MISSES")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
miss_rate = d_ratio(total_miss, total_miss + total_hit)
|
||||
|
|
@ -508,7 +509,7 @@ def IntelIotlb() -> Optional[MetricGroup]:
|
|||
"100%",
|
||||
),
|
||||
]
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return MetricGroup(
|
||||
|
|
@ -519,59 +520,92 @@ def IntelIotlb() -> Optional[MetricGroup]:
|
|||
|
||||
|
||||
def IntelL2() -> Optional[MetricGroup]:
|
||||
assert _args is not None
|
||||
try:
|
||||
DC_HIT = Event("L2_RQSTS.DEMAND_DATA_RD_HIT")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
try:
|
||||
DC_MISS = Event("L2_RQSTS.DEMAND_DATA_RD_MISS")
|
||||
l2_dmnd_miss = DC_MISS
|
||||
l2_dmnd_rd_all = DC_MISS + DC_HIT
|
||||
except:
|
||||
l2_dmnd_miss: Expression = DC_MISS
|
||||
l2_dmnd_rd_all: Expression = DC_MISS + DC_HIT
|
||||
except ValueError:
|
||||
DC_ALL = Event("L2_RQSTS.ALL_DEMAND_DATA_RD")
|
||||
l2_dmnd_miss = DC_ALL - DC_HIT
|
||||
l2_dmnd_rd_all = DC_ALL
|
||||
l2_dmnd_mrate = d_ratio(l2_dmnd_miss, interval_sec)
|
||||
l2_dmnd_rrate = d_ratio(l2_dmnd_rd_all, interval_sec)
|
||||
|
||||
DC_PFH = None
|
||||
DC_PFM = None
|
||||
l2_pf_all = None
|
||||
l2_pf_mrate = None
|
||||
l2_pf_rrate = None
|
||||
l2_useless_rate = None
|
||||
try:
|
||||
DC_OUT_U = Event("L2_LINES_OUT.USELESS_HWPF")
|
||||
l2_pf_useless = DC_OUT_U
|
||||
l2_useless_rate = d_ratio(l2_pf_useless, interval_sec)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
hwpf_group = None
|
||||
try:
|
||||
DC_PFH = Event("L2_RQSTS.PF_HIT")
|
||||
DC_PFM = Event("L2_RQSTS.PF_MISS")
|
||||
l2_pf_all = DC_PFH + DC_PFM
|
||||
l2_pf_mrate = d_ratio(DC_PFM, interval_sec)
|
||||
l2_pf_rrate = d_ratio(l2_pf_all, interval_sec)
|
||||
except:
|
||||
hwpf_group = MetricGroup("lpm_l2_hwpf", [
|
||||
Metric("lpm_l2_hwpf_hits", "L2 cache hardware prefetcher hits",
|
||||
d_ratio(DC_PFH, l2_pf_all), "100%"),
|
||||
Metric("lpm_l2_hwpf_misses", "L2 cache hardware prefetcher misses",
|
||||
d_ratio(DC_PFM, l2_pf_all), "100%"),
|
||||
Metric("lpm_l2_hwpf_useless", "L2 cache hardware prefetcher useless prefetches per second",
|
||||
l2_useless_rate, "100%") if l2_useless_rate else None,
|
||||
Metric("lpm_l2_hwpf_requests", "L2 cache hardware prefetcher requests per second",
|
||||
l2_pf_rrate, "100%"),
|
||||
Metric("lpm_l2_hwpf_misses", "L2 cache hardware prefetcher misses per second",
|
||||
l2_pf_mrate, "100%"),
|
||||
])
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
DC_RFOH = None
|
||||
DC_RFOM = None
|
||||
l2_rfo_all = None
|
||||
l2_rfo_mrate = None
|
||||
l2_rfo_rrate = None
|
||||
rfo_group = None
|
||||
try:
|
||||
DC_RFOH = Event("L2_RQSTS.RFO_HIT")
|
||||
DC_RFOM = Event("L2_RQSTS.RFO_MISS")
|
||||
l2_rfo_all = DC_RFOH + DC_RFOM
|
||||
l2_rfo_mrate = d_ratio(DC_RFOM, interval_sec)
|
||||
l2_rfo_rrate = d_ratio(l2_rfo_all, interval_sec)
|
||||
except:
|
||||
rfo_group = MetricGroup("lpm_l2_rfo", [
|
||||
Metric("lpm_l2_rfo_hits", "L2 cache request for ownership (RFO) hits",
|
||||
d_ratio(DC_RFOH, l2_rfo_all), "100%"),
|
||||
Metric("lpm_l2_rfo_misses", "L2 cache request for ownership (RFO) misses",
|
||||
d_ratio(DC_RFOM, l2_rfo_all), "100%"),
|
||||
Metric("lpm_l2_rfo_requests", "L2 cache request for ownership (RFO) requests per second",
|
||||
l2_rfo_rrate, "requests/s"),
|
||||
Metric("lpm_l2_rfo_misses", "L2 cache request for ownership (RFO) misses per second",
|
||||
l2_rfo_mrate, "misses/s"),
|
||||
])
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
DC_CH = None
|
||||
try:
|
||||
DC_CH = Event("L2_RQSTS.CODE_RD_HIT")
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
DC_CM = Event("L2_RQSTS.CODE_RD_MISS")
|
||||
DC_IN = Event("L2_LINES_IN.ALL")
|
||||
DC_OUT_NS = None
|
||||
DC_OUT_S = None
|
||||
l2_lines_out = None
|
||||
|
||||
DC_WB_U = None
|
||||
DC_WB_D = None
|
||||
wbu = None
|
||||
wbd = None
|
||||
try:
|
||||
DC_WB_U = Event("IDI_MISC.WB_UPGRADE")
|
||||
DC_WB_D = Event("IDI_MISC.WB_DOWNGRADE")
|
||||
wbu = d_ratio(DC_WB_U, interval_sec)
|
||||
wbd = d_ratio(DC_WB_D, interval_sec)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
l2_out_rate = None
|
||||
wbn = None
|
||||
isd = None
|
||||
|
|
@ -583,43 +617,24 @@ def IntelL2() -> Optional[MetricGroup]:
|
|||
"L2_LINES_OUT.DEMAND_CLEAN",
|
||||
"L2_LINES_IN.I")
|
||||
if DC_OUT_S.name == "L2_LINES_OUT.SILENT" and (
|
||||
args.model.startswith("skylake") or
|
||||
args.model == "cascadelakex"):
|
||||
_args.model.startswith("skylake") or
|
||||
_args.model == "cascadelakex"):
|
||||
DC_OUT_S.name = "L2_LINES_OUT.SILENT/any/"
|
||||
# bring is back to per-CPU
|
||||
l2_s = Select(DC_OUT_S / 2, Literal("#smt_on"), DC_OUT_S)
|
||||
l2_ns = DC_OUT_NS
|
||||
l2_lines_out = l2_s + l2_ns
|
||||
l2_out_rate = d_ratio(l2_lines_out, interval_sec)
|
||||
nlr = max(l2_ns - DC_WB_U - DC_WB_D, 0)
|
||||
wbn = d_ratio(nlr, interval_sec)
|
||||
if DC_WB_U and DC_WB_D:
|
||||
nlr = max(l2_ns - DC_WB_U - DC_WB_D, 0)
|
||||
wbn = d_ratio(nlr, interval_sec)
|
||||
isd = d_ratio(l2_s, interval_sec)
|
||||
except:
|
||||
pass
|
||||
DC_OUT_U = None
|
||||
l2_pf_useless = None
|
||||
l2_useless_rate = None
|
||||
try:
|
||||
DC_OUT_U = Event("L2_LINES_OUT.USELESS_HWPF")
|
||||
l2_pf_useless = DC_OUT_U
|
||||
l2_useless_rate = d_ratio(l2_pf_useless, interval_sec)
|
||||
except:
|
||||
pass
|
||||
DC_WB_U = None
|
||||
DC_WB_D = None
|
||||
wbu = None
|
||||
wbd = None
|
||||
try:
|
||||
DC_WB_U = Event("IDI_MISC.WB_UPGRADE")
|
||||
DC_WB_D = Event("IDI_MISC.WB_DOWNGRADE")
|
||||
wbu = d_ratio(DC_WB_U, interval_sec)
|
||||
wbd = d_ratio(DC_WB_D, interval_sec)
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
l2_lines_in = DC_IN
|
||||
l2_code_all = (DC_CH + DC_CM) if DC_CH else None
|
||||
l2_code_rate = d_ratio(l2_code_all, interval_sec) if DC_CH else None
|
||||
l2_code_rate = d_ratio(l2_code_all, interval_sec) if l2_code_all else None
|
||||
l2_code_miss_rate = d_ratio(DC_CM, interval_sec)
|
||||
l2_in_rate = d_ratio(l2_lines_in, interval_sec)
|
||||
|
||||
|
|
@ -640,35 +655,15 @@ def IntelL2() -> Optional[MetricGroup]:
|
|||
Metric("lpm_l2_rd_misses", "L2 cache data read misses per second",
|
||||
l2_dmnd_mrate, "misses/s"),
|
||||
]),
|
||||
MetricGroup("lpm_l2_hwpf", [
|
||||
Metric("lpm_l2_hwpf_hits", "L2 cache hardware prefetcher hits",
|
||||
d_ratio(DC_PFH, l2_pf_all), "100%"),
|
||||
Metric("lpm_l2_hwpf_misses", "L2 cache hardware prefetcher misses",
|
||||
d_ratio(DC_PFM, l2_pf_all), "100%"),
|
||||
Metric("lpm_l2_hwpf_useless", "L2 cache hardware prefetcher useless prefetches per second",
|
||||
l2_useless_rate, "100%") if l2_useless_rate else None,
|
||||
Metric("lpm_l2_hwpf_requests", "L2 cache hardware prefetcher requests per second",
|
||||
l2_pf_rrate, "100%"),
|
||||
Metric("lpm_l2_hwpf_misses", "L2 cache hardware prefetcher misses per second",
|
||||
l2_pf_mrate, "100%"),
|
||||
]) if DC_PFH else None,
|
||||
MetricGroup("lpm_l2_rfo", [
|
||||
Metric("lpm_l2_rfo_hits", "L2 cache request for ownership (RFO) hits",
|
||||
d_ratio(DC_RFOH, l2_rfo_all), "100%"),
|
||||
Metric("lpm_l2_rfo_misses", "L2 cache request for ownership (RFO) misses",
|
||||
d_ratio(DC_RFOM, l2_rfo_all), "100%"),
|
||||
Metric("lpm_l2_rfo_requests", "L2 cache request for ownership (RFO) requests per second",
|
||||
l2_rfo_rrate, "requests/s"),
|
||||
Metric("lpm_l2_rfo_misses", "L2 cache request for ownership (RFO) misses per second",
|
||||
l2_rfo_mrate, "misses/s"),
|
||||
]) if DC_RFOH else None,
|
||||
hwpf_group,
|
||||
rfo_group,
|
||||
MetricGroup("lpm_l2_code", [
|
||||
Metric("lpm_l2_code_hits", "L2 cache code hits",
|
||||
d_ratio(DC_CH, l2_code_all), "100%") if DC_CH else None,
|
||||
d_ratio(DC_CH, l2_code_all), "100%") if DC_CH and l2_code_all else None,
|
||||
Metric("lpm_l2_code_misses", "L2 cache code misses",
|
||||
d_ratio(DC_CM, l2_code_all), "100%") if DC_CH else None,
|
||||
d_ratio(DC_CM, l2_code_all), "100%") if DC_CH and l2_code_all else None,
|
||||
Metric("lpm_l2_code_requests", "L2 cache code requests per second",
|
||||
l2_code_rate, "requests/s") if DC_CH else None,
|
||||
l2_code_rate, "requests/s") if l2_code_rate else None,
|
||||
Metric("lpm_l2_code_misses", "L2 cache code misses per second",
|
||||
l2_code_miss_rate, "misses/s"),
|
||||
]),
|
||||
|
|
@ -706,7 +701,7 @@ def IntelMissLat() -> Optional[MetricGroup]:
|
|||
"UNC_CHA_TOR_INSERTS.IA_MISS",
|
||||
"UNC_C_TOR_INSERTS.MISS_REMOTE_OPCODE",
|
||||
"UNC_C_TOR_INSERTS.NID_MISS_OPCODE")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
if (data_rd_loc_occ.name == "UNC_C_TOR_OCCUPANCY.MISS_LOCAL_OPCODE" or
|
||||
|
|
@ -752,8 +747,8 @@ def IntelMissLat() -> Optional[MetricGroup]:
|
|||
def IntelMlp() -> Optional[Metric]:
|
||||
try:
|
||||
l1d = Event("L1D_PEND_MISS.PENDING")
|
||||
l1dc = Event("L1D_PEND_MISS.PENDING_CYCLES")
|
||||
except:
|
||||
l1dc: Expression = Event("L1D_PEND_MISS.PENDING_CYCLES")
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
l1dc = Select(l1dc / 2, Literal("#smt_on"), l1dc)
|
||||
|
|
@ -764,8 +759,9 @@ def IntelMlp() -> Optional[Metric]:
|
|||
|
||||
|
||||
def IntelPorts() -> Optional[MetricGroup]:
|
||||
pipeline_events = json.load(
|
||||
open(f"{_args.events_path}/x86/{_args.model}/pipeline.json"))
|
||||
assert _args is not None
|
||||
with open(f"{_args.events_path}/x86/{_args.model}/pipeline.json", encoding="utf-8") as f:
|
||||
pipeline_events = json.load(f)
|
||||
|
||||
core_cycles = Event("CPU_CLK_UNHALTED.THREAD_P_ANY",
|
||||
"CPU_CLK_UNHALTED.DISTRIBUTED",
|
||||
|
|
@ -777,11 +773,10 @@ def IntelPorts() -> Optional[MetricGroup]:
|
|||
for x in pipeline_events:
|
||||
if "EventName" in x and re.search("^UOPS_DISPATCHED.PORT", x["EventName"]):
|
||||
name = x["EventName"]
|
||||
port = re.search(r"(PORT_[0-9].*)", name).group(0).lower()
|
||||
if name.endswith("_CORE"):
|
||||
cyc = core_cycles
|
||||
else:
|
||||
cyc = smt_cycles
|
||||
match = re.search(r"(PORT_[0-9].*)", name)
|
||||
assert match is not None
|
||||
port = match.group(0).lower()
|
||||
cyc: Expression = core_cycles if name.endswith("_CORE") else smt_cycles
|
||||
metrics.append(Metric(f"lpm_{port}", f"{port} utilization (higher is better)",
|
||||
d_ratio(Event(name), cyc), "100%"))
|
||||
if len(metrics) == 0:
|
||||
|
|
@ -800,7 +795,7 @@ def IntelSwpf() -> Optional[MetricGroup]:
|
|||
s_t0 = Event("SW_PREFETCH_ACCESS.T0")
|
||||
s_t1 = Event("SW_PREFETCH_ACCESS.T1_T2")
|
||||
s_w = Event("SW_PREFETCH_ACCESS.PREFETCHW")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
all_sw = s_nta + s_t0 + s_t1 + s_w
|
||||
|
|
@ -857,6 +852,7 @@ def IntelSwpf() -> Optional[MetricGroup]:
|
|||
|
||||
|
||||
def IntelLdSt() -> Optional[MetricGroup]:
|
||||
assert _args is not None
|
||||
if _args.model in [
|
||||
"bonnell",
|
||||
"nehalemep",
|
||||
|
|
@ -882,12 +878,12 @@ def IntelLdSt() -> Optional[MetricGroup]:
|
|||
LDST_PRE = None
|
||||
try:
|
||||
LDST_PRE = Event("LOAD_HIT_PREFETCH.SWPF", "LOAD_HIT_PRE.SW_PF")
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
LDST_AT = None
|
||||
try:
|
||||
LDST_AT = Event("MEM_INST_RETIRED.LOCK_LOADS")
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
cyc = LDST_CYC
|
||||
|
||||
|
|
@ -945,8 +941,8 @@ def UncoreCState() -> Optional[MetricGroup]:
|
|||
pcu_ticks = Event("UNC_P_CLOCKTICKS")
|
||||
c0 = Event("UNC_P_POWER_STATE_OCCUPANCY.CORES_C0")
|
||||
c3 = Event("UNC_P_POWER_STATE_OCCUPANCY.CORES_C3")
|
||||
c6 = Event("UNC_P_POWER_STATE_OCCUPANCY.CORES_C6")
|
||||
except:
|
||||
c6: Expression = Event("UNC_P_POWER_STATE_OCCUPANCY.CORES_C6")
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
num_cores = Literal("#num_cores") / Literal("#num_packages")
|
||||
|
|
@ -981,13 +977,10 @@ def UncoreDir() -> Optional[MetricGroup]:
|
|||
cha_upd = Event("UNC_CHA_DIR_UPDATE.HA")
|
||||
# Turn the umask into a ANY rather than HA filter.
|
||||
cha_upd.name += "/umask=3,name=UNC_CHA_DIR_UPDATE.ANY/"
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
m2m_total = m2m_hits + m2m_miss
|
||||
upd = m2m_upd + cha_upd # in cache lines
|
||||
upd_r = upd / interval_sec
|
||||
look_r = m2m_total / interval_sec
|
||||
|
||||
scale = 64 / 1_000_000 # Cache lines to MB
|
||||
return MetricGroup("lpm_dir", [
|
||||
|
|
@ -1014,7 +1007,7 @@ def UncoreMem() -> Optional[MetricGroup]:
|
|||
"UNC_H_REQUESTS.WRITES_LOCAL")
|
||||
rem_wrs = Event("UNC_CHA_REQUESTS.WRITES_REMOTE",
|
||||
"UNC_H_REQUESTS.WRITES_REMOTE")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
scale = 64 / 1_000_000
|
||||
|
|
@ -1035,16 +1028,18 @@ def UncoreMem() -> Optional[MetricGroup]:
|
|||
|
||||
|
||||
def UncoreMemBw() -> Optional[MetricGroup]:
|
||||
assert _args is not None
|
||||
mem_events = []
|
||||
try:
|
||||
mem_events = json.load(open(f"{os.path.dirname(os.path.realpath(__file__))}"
|
||||
f"/arch/x86/{args.model}/uncore-memory.json"))
|
||||
except:
|
||||
with open(f"{os.path.dirname(os.path.realpath(__file__))}"
|
||||
f"/arch/x86/{_args.model}/uncore-memory.json", encoding="utf-8") as f:
|
||||
mem_events = json.load(f)
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
|
||||
ddr_rds = 0
|
||||
ddr_wrs = 0
|
||||
ddr_total = 0
|
||||
ddr_rds: Union[int, Expression] = 0
|
||||
ddr_wrs: Union[int, Expression] = 0
|
||||
ddr_total: Union[int, Expression] = 0
|
||||
for x in mem_events:
|
||||
if "EventName" in x:
|
||||
name = x["EventName"]
|
||||
|
|
@ -1059,17 +1054,17 @@ def UncoreMemBw() -> Optional[MetricGroup]:
|
|||
try:
|
||||
ddr_rds = Event("UNC_M_CAS_COUNT.RD")
|
||||
ddr_wrs = Event("UNC_M_CAS_COUNT.WR")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
ddr_total = ddr_rds + ddr_wrs
|
||||
|
||||
pmm_rds = 0
|
||||
pmm_wrs = 0
|
||||
pmm_rds: Union[int, Expression] = 0
|
||||
pmm_wrs: Union[int, Expression] = 0
|
||||
try:
|
||||
pmm_rds = Event("UNC_M_PMM_RPQ_INSERTS")
|
||||
pmm_wrs = Event("UNC_M_PMM_WPQ_INSERTS")
|
||||
except:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
pmm_total = pmm_rds + pmm_wrs
|
||||
|
|
@ -1101,7 +1096,7 @@ def UncoreMemSat() -> Optional[Metric]:
|
|||
sat = Event("UNC_CHA_DISTRESS_ASSERTED.VERT", "UNC_CHA_FAST_ASSERTED.VERT",
|
||||
"UNC_C_FAST_ASSERTED", "UNC_CHA_DISTRESS_ASSERTED.DPT_ANY",
|
||||
"UNC_CHA_DISTRESS_ASSERTED.DPT_NONLOCAL")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
desc = ("Mesh Bandwidth saturation (% CBOX cycles with FAST signal asserted, "
|
||||
|
|
@ -1116,11 +1111,9 @@ def UncoreUpiBw() -> Optional[MetricGroup]:
|
|||
try:
|
||||
upi_rds = Event("UNC_UPI_RxL_FLITS.ALL_DATA")
|
||||
upi_wrs = Event("UNC_UPI_TxL_FLITS.ALL_DATA")
|
||||
except:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
upi_total = upi_rds + upi_wrs
|
||||
|
||||
# From "Uncore Performance Monitoring": When measuring the amount of
|
||||
# bandwidth consumed by transmission of the data (i.e. NOT including
|
||||
# the header), it should be .ALL_DATA / 9 * 64B.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"""Convert directories of JSON events to C code."""
|
||||
import argparse
|
||||
import csv
|
||||
from functools import lru_cache
|
||||
import json
|
||||
import metric
|
||||
import os
|
||||
|
|
@ -22,7 +21,7 @@ _metric_tables: list[str] = []
|
|||
# List of metric tables generated from "/sys" directories.
|
||||
_sys_metric_tables: list[str] = []
|
||||
# Mapping between sys event table names and sys metric table names.
|
||||
_sys_event_table_to_metric_table_mapping = {}
|
||||
_sys_event_table_to_metric_table_mapping: Dict[str, str] = {}
|
||||
# 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.
|
||||
|
|
@ -38,7 +37,7 @@ _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.
|
||||
_metricgroups = {}
|
||||
_metricgroups: Dict[str, str] = {}
|
||||
# Order specific JsonEvent attributes will be visited.
|
||||
_json_event_attributes = [
|
||||
# cmp_sevent related attributes.
|
||||
|
|
@ -115,17 +114,17 @@ class BigCString:
|
|||
|
||||
def __init__(self):
|
||||
self.strings = set()
|
||||
self.insert_number = 0;
|
||||
self.insert_number = 0
|
||||
self.insert_point = {}
|
||||
self.metrics = set()
|
||||
|
||||
def add(self, s: str, metric: bool) -> None:
|
||||
def add(self, s: str, is_metric: bool) -> None:
|
||||
"""Called to add to the big string."""
|
||||
if s not in self.strings:
|
||||
self.strings.add(s)
|
||||
self.insert_point[s] = self.insert_number
|
||||
self.insert_number += 1
|
||||
if metric:
|
||||
if is_metric:
|
||||
self.metrics.add(s)
|
||||
|
||||
def compute(self) -> None:
|
||||
|
|
@ -303,7 +302,7 @@ class JsonEvent:
|
|||
return int(val, 16) == 0
|
||||
else:
|
||||
return int(val) == 0
|
||||
except:
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def canonicalize_value(val: str) -> str:
|
||||
|
|
@ -311,7 +310,7 @@ class JsonEvent:
|
|||
if val.startswith('0x'):
|
||||
return llx(int(val, 16))
|
||||
return str(int(val))
|
||||
except:
|
||||
except ValueError:
|
||||
return val
|
||||
|
||||
eventcode = 0
|
||||
|
|
@ -426,15 +425,15 @@ class JsonEvent:
|
|||
s += f'\t{attr} = {value},\n'
|
||||
return s + '}'
|
||||
|
||||
def build_c_string(self, metric: bool) -> str:
|
||||
def build_c_string(self, is_metric: bool) -> str:
|
||||
s = ''
|
||||
for attr in _json_metric_attributes if metric else _json_event_attributes:
|
||||
for attr in _json_metric_attributes if is_metric else _json_event_attributes:
|
||||
x = getattr(self, attr)
|
||||
if metric and x and attr == 'metric_expr':
|
||||
if is_metric and x and attr == 'metric_expr':
|
||||
# Convert parsed metric expressions into a string. Slashes
|
||||
# must be doubled in the file.
|
||||
x = x.ToPerfJson().replace('\\', '\\\\')
|
||||
if metric and x and attr == 'metric_threshold':
|
||||
if is_metric and x and attr == 'metric_threshold':
|
||||
x = x.replace('\\', '\\\\')
|
||||
if attr in _json_enum_attributes:
|
||||
s += x if x else '0'
|
||||
|
|
@ -442,24 +441,25 @@ class JsonEvent:
|
|||
s += f'{x}\\000' if x else '\\000'
|
||||
return s
|
||||
|
||||
def to_c_string(self, metric: bool) -> str:
|
||||
def to_c_string(self, is_metric: bool) -> str:
|
||||
"""Representation of the event as a C struct initializer."""
|
||||
|
||||
def make_comment(s: str) -> str:
|
||||
s = s.replace('*/', r'\*\/')
|
||||
return f'\t/* {s} */\n' if len(s) < 80 else f'\t/* {s[0:80]}... */\n'
|
||||
|
||||
s = self.build_c_string(metric)
|
||||
s = self.build_c_string(is_metric)
|
||||
assert _bcs is not None
|
||||
return f'{make_comment(s)}\t{{ { _bcs.offsets[s] } }},\n'
|
||||
|
||||
|
||||
_json_cache = {}
|
||||
_json_cache: Dict[Tuple[str, str], Sequence[JsonEvent]] = {}
|
||||
def _read_json_events_impl(path: str, topic: str) -> Sequence[JsonEvent]:
|
||||
"""Read json events from the specified file."""
|
||||
try:
|
||||
events = json.load(open(path), object_hook=JsonEvent)
|
||||
except BaseException as err:
|
||||
with open(path, encoding='utf-8') as f:
|
||||
events = json.load(f, object_hook=JsonEvent)
|
||||
except BaseException:
|
||||
print(f"Exception processing {path}")
|
||||
raise
|
||||
metrics: list[Tuple[str, str, metric.Expression]] = []
|
||||
|
|
@ -483,7 +483,6 @@ def read_json_events(path: str, topic: str) -> Sequence[JsonEvent]:
|
|||
|
||||
def preprocess_arch_std_files(archpath: str) -> None:
|
||||
"""Read in all architecture standard events."""
|
||||
global _arch_std_events
|
||||
for item in os.scandir(archpath):
|
||||
if not item.is_file() or not item.name.endswith('.json'):
|
||||
continue
|
||||
|
|
@ -523,13 +522,10 @@ def print_pending_events() -> None:
|
|||
if not _pending_events:
|
||||
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)
|
||||
else:
|
||||
global event_tables
|
||||
_event_tables.append(_pending_events_tblname)
|
||||
|
||||
first = True
|
||||
|
|
@ -550,7 +546,7 @@ def print_pending_events() -> None:
|
|||
last_pmu = event.pmu
|
||||
pmus.add((event.pmu, pmu_name))
|
||||
|
||||
_args.output_file.write(event.to_c_string(metric=False))
|
||||
_args.output_file.write(event.to_c_string(is_metric=False))
|
||||
last_name = event.name
|
||||
_pending_events = []
|
||||
|
||||
|
|
@ -586,31 +582,28 @@ def print_pending_metrics() -> None:
|
|||
if not _pending_metrics:
|
||||
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)
|
||||
else:
|
||||
global metric_tables
|
||||
_metric_tables.append(_pending_metrics_tblname)
|
||||
|
||||
first = True
|
||||
last_pmu = None
|
||||
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:
|
||||
for m in sorted(_pending_metrics, key=metric_cmp_key):
|
||||
if m.pmu != last_pmu:
|
||||
if not first:
|
||||
_args.output_file.write('};\n')
|
||||
pmu_name = metric.pmu.replace(',', '_')
|
||||
pmu_name = m.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))
|
||||
last_pmu = m.pmu
|
||||
pmus.add((m.pmu, pmu_name))
|
||||
|
||||
_args.output_file.write(metric.to_c_string(metric=True))
|
||||
_args.output_file.write(m.to_c_string(is_metric=True))
|
||||
_pending_metrics = []
|
||||
|
||||
_args.output_file.write(f"""
|
||||
|
|
@ -649,13 +642,14 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
|
|||
|
||||
assert _bcs is not None
|
||||
if item.name.endswith('metricgroups.json'):
|
||||
metricgroup_descriptions = json.load(open(item.path))
|
||||
with open(item.path, encoding='utf-8') as f:
|
||||
metricgroup_descriptions = json.load(f)
|
||||
for mgroup in metricgroup_descriptions:
|
||||
assert len(mgroup) > 1, parents
|
||||
description = f"{metricgroup_descriptions[mgroup]}\\000"
|
||||
mgroup = f"{mgroup}\\000"
|
||||
_bcs.add(mgroup, metric=True)
|
||||
_bcs.add(description, metric=True)
|
||||
_bcs.add(mgroup, is_metric=True)
|
||||
_bcs.add(description, is_metric=True)
|
||||
_metricgroups[mgroup] = description
|
||||
return
|
||||
|
||||
|
|
@ -663,11 +657,12 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
|
|||
for event in read_json_events(item.path, topic):
|
||||
pmu_name = f"{event.pmu}\\000"
|
||||
if event.name:
|
||||
_bcs.add(pmu_name, metric=False)
|
||||
_bcs.add(event.build_c_string(metric=False), metric=False)
|
||||
_bcs.add(pmu_name, is_metric=False)
|
||||
_bcs.add(event.build_c_string(is_metric=False), is_metric=False)
|
||||
if event.metric_name:
|
||||
_bcs.add(pmu_name, metric=True)
|
||||
_bcs.add(event.build_c_string(metric=True), metric=True)
|
||||
pmu_name = f"{event.pmu}\\000"
|
||||
_bcs.add(pmu_name, is_metric=True)
|
||||
_bcs.add(event.build_c_string(is_metric=True), is_metric=True)
|
||||
|
||||
def process_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
|
||||
"""Process a JSON file during the main walk."""
|
||||
|
|
@ -777,7 +772,7 @@ static const struct pmu_events_map pmu_events_map[] = {
|
|||
},
|
||||
""")
|
||||
else:
|
||||
with open(f'{_args.starting_dir}/{arch}/mapfile.csv') as csvfile:
|
||||
with open(f'{_args.starting_dir}/{arch}/mapfile.csv', encoding='utf-8') as csvfile:
|
||||
table = csv.reader(csvfile)
|
||||
first = True
|
||||
for row in table:
|
||||
|
|
@ -871,8 +866,8 @@ 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."""
|
||||
assert _args is not None
|
||||
_args.output_file.write("""
|
||||
struct pmu_sys_events {
|
||||
\tconst char *name;
|
||||
|
|
@ -1481,7 +1476,7 @@ def main() -> None:
|
|||
except Exception as e:
|
||||
raise RuntimeError(f'Action failure for \'{item.name}\' in {parents}') from e
|
||||
if item.is_dir():
|
||||
ftw(item.path, parents + [item.name], action)
|
||||
ftw(item.path, list(parents) + [item.name], action)
|
||||
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument('arch', help='Architecture name like x86')
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ hw_cache_result = [
|
|||
"misses"),
|
||||
]
|
||||
|
||||
events = []
|
||||
events: list[dict[str, str]] = []
|
||||
def add_event(name: str,
|
||||
cache_id: int, cache_op: int, cache_result: int,
|
||||
desc: str,
|
||||
|
|
@ -87,10 +87,10 @@ def add_event(name: str,
|
|||
event["Deprecated"] = "1"
|
||||
events.append(event)
|
||||
|
||||
for (cache_id, names, ops, cache_desc) in hw_cache_id:
|
||||
for name in names:
|
||||
add_event(name,
|
||||
cache_id,
|
||||
for (cid, names, ops, cache_desc) in hw_cache_id:
|
||||
for cname in names:
|
||||
add_event(cname,
|
||||
cid,
|
||||
0, # PERF_COUNT_HW_CACHE_OP_READ
|
||||
0, # PERF_COUNT_HW_CACHE_RESULT_ACCESS
|
||||
f"{cache_desc} read accesses.",
|
||||
|
|
@ -100,27 +100,29 @@ for (cache_id, names, ops, cache_desc) in hw_cache_id:
|
|||
if op not in ops:
|
||||
continue
|
||||
for op_name in op_names:
|
||||
deprecated = (names[0] != name or op_names[1] != op_name)
|
||||
add_event(f"{name}-{op_name}",
|
||||
cache_id,
|
||||
is_deprecated = (names[0] != cname or op_names[1] != op_name)
|
||||
add_event(f"{cname}-{op_name}",
|
||||
cid,
|
||||
op,
|
||||
0, # PERF_COUNT_HW_CACHE_RESULT_ACCESS
|
||||
f"{cache_desc} {op_desc} accesses.",
|
||||
deprecated)
|
||||
is_deprecated)
|
||||
|
||||
for (result, result_names, result_desc) in hw_cache_result:
|
||||
for result_name in result_names:
|
||||
deprecated = ((names[0] != name or op_names[0] != op_name) or
|
||||
(result == 0) or (result_names[0] != result_name))
|
||||
add_event(f"{name}-{op_name}-{result_name}",
|
||||
cache_id, op, result,
|
||||
is_deprecated = ((names[0] != cname or op_names[0] != op_name) or
|
||||
(result == 0) or (result_names[0] != result_name))
|
||||
add_event(f"{cname}-{op_name}-{result_name}",
|
||||
cid,
|
||||
op,
|
||||
result,
|
||||
f"{cache_desc} {op_desc} {result_desc}.",
|
||||
deprecated)
|
||||
is_deprecated)
|
||||
|
||||
for (result, result_names, result_desc) in hw_cache_result:
|
||||
for result_name in result_names:
|
||||
add_event(f"{name}-{result_name}",
|
||||
cache_id,
|
||||
add_event(f"{cname}-{result_name}",
|
||||
cid,
|
||||
0, # PERF_COUNT_HW_CACHE_OP_READ
|
||||
result,
|
||||
f"{cache_desc} read {result_desc}.",
|
||||
|
|
|
|||
|
|
@ -6,18 +6,16 @@ import json
|
|||
import os
|
||||
import re
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Optional, Set, Tuple, Union
|
||||
from typing import Dict, List, Optional, Sequence, Set, Tuple, Union
|
||||
|
||||
all_pmus = set()
|
||||
all_events = set()
|
||||
experimental_events = set()
|
||||
all_events_all_models = set()
|
||||
all_pmus: Set[str] = set()
|
||||
all_events: Set[str] = set()
|
||||
experimental_events: Set[str] = set()
|
||||
all_events_all_models: Set[str] = set()
|
||||
|
||||
def LoadEvents(directory: str) -> None:
|
||||
"""Populate a global set of all known events for the purpose of validating Event names"""
|
||||
global all_pmus
|
||||
global all_events
|
||||
global experimental_events
|
||||
global all_events_all_models
|
||||
all_events = {
|
||||
"context\\-switches",
|
||||
|
|
@ -30,29 +28,31 @@ def LoadEvents(directory: str) -> None:
|
|||
filename = os.fsdecode(file)
|
||||
if filename.endswith(".json"):
|
||||
try:
|
||||
for x in json.load(open(f"{directory}/{filename}")):
|
||||
if "Unit" in x:
|
||||
all_pmus.add(x["Unit"])
|
||||
if "EventName" in x:
|
||||
all_events.add(x["EventName"])
|
||||
if "Experimental" in x and x["Experimental"] == "1":
|
||||
experimental_events.add(x["EventName"])
|
||||
elif "ArchStdEvent" in x:
|
||||
all_events.add(x["ArchStdEvent"])
|
||||
with open(f"{directory}/{filename}", encoding="utf-8") as f:
|
||||
for x in json.load(f):
|
||||
if "Unit" in x:
|
||||
all_pmus.add(x["Unit"])
|
||||
if "EventName" in x:
|
||||
all_events.add(x["EventName"])
|
||||
if "Experimental" in x and x["Experimental"] == "1":
|
||||
experimental_events.add(x["EventName"])
|
||||
elif "ArchStdEvent" in x:
|
||||
all_events.add(x["ArchStdEvent"])
|
||||
except json.decoder.JSONDecodeError:
|
||||
# The generated directory may be the same as the input, which
|
||||
# causes partial json files. Ignore errors.
|
||||
pass
|
||||
all_events_all_models = all_events.copy()
|
||||
for root, dirs, files in os.walk(directory + ".."):
|
||||
for root, _, files in os.walk(directory + ".."):
|
||||
for filename in files:
|
||||
if filename.endswith(".json"):
|
||||
try:
|
||||
for x in json.load(open(f"{root}/{filename}")):
|
||||
if "EventName" in x:
|
||||
all_events_all_models.add(x["EventName"])
|
||||
elif "ArchStdEvent" in x:
|
||||
all_events_all_models.add(x["ArchStdEvent"])
|
||||
with open(f"{root}/{filename}", encoding="utf-8") as f:
|
||||
for x in json.load(f):
|
||||
if "EventName" in x:
|
||||
all_events_all_models.add(x["EventName"])
|
||||
elif "ArchStdEvent" in x:
|
||||
all_events_all_models.add(x["ArchStdEvent"])
|
||||
except json.decoder.JSONDecodeError:
|
||||
# The generated directory may be the same as the input, which
|
||||
# causes partial json files. Ignore errors.
|
||||
|
|
@ -65,7 +65,6 @@ def CheckPmu(name: str) -> bool:
|
|||
|
||||
def CheckEvent(name: str) -> bool:
|
||||
"""Check the event name exists in the set of all loaded events"""
|
||||
global all_events
|
||||
if len(all_events) == 0:
|
||||
# No events loaded so assume any event is good.
|
||||
return True
|
||||
|
|
@ -81,7 +80,6 @@ def CheckEvent(name: str) -> bool:
|
|||
|
||||
def CheckEveryEvent(*names: str) -> None:
|
||||
"""Check all the events exist in at least one json file"""
|
||||
global all_events_all_models
|
||||
if len(all_events_all_models) == 0:
|
||||
assert len(names) == 1, f"Cannot determine valid events in {names}"
|
||||
# No events loaded so assume any event is good.
|
||||
|
|
@ -96,11 +94,10 @@ def CheckEveryEvent(*names: str) -> None:
|
|||
if any([name.startswith(x) for x in ['amd', 'arm', 'cpu', 'msr', 'power', 'cha', 'uncore']]):
|
||||
continue
|
||||
if name not in all_events_all_models:
|
||||
raise Exception(f"Is {name} a named json event?")
|
||||
raise ValueError(f"Is {name} a named json event?")
|
||||
|
||||
|
||||
def IsExperimentalEvent(name: str) -> bool:
|
||||
global experimental_events
|
||||
if ':' in name:
|
||||
# Remove trailing modifier.
|
||||
name = name[:name.find(':')]
|
||||
|
|
@ -447,14 +444,13 @@ class Event(Expression):
|
|||
error += " or " + name
|
||||
else:
|
||||
error = name
|
||||
global all_events
|
||||
raise Exception(f"No event {error} in:\n{all_events}")
|
||||
raise ValueError(f"No event {error} in:\n{all_events}")
|
||||
|
||||
def HasExperimentalEvents(self) -> bool:
|
||||
return IsExperimentalEvent(self.name)
|
||||
|
||||
def ToPerfJson(self):
|
||||
result = re.sub('/', '@', self.name)
|
||||
result = re.sub('/', '@', _FixEscapes(self.name))
|
||||
return result
|
||||
|
||||
def ToPython(self):
|
||||
|
|
@ -655,7 +651,7 @@ class Metric:
|
|||
|
||||
return result
|
||||
|
||||
def ToMetricGroupDescriptions(self, root: bool = True) -> Dict[str, str]:
|
||||
def ToMetricGroupDescriptions(self, _root: bool = True) -> Dict[str, str]:
|
||||
return {}
|
||||
|
||||
class MetricGroup:
|
||||
|
|
@ -667,7 +663,7 @@ class MetricGroup:
|
|||
"""
|
||||
|
||||
def __init__(self, name: str,
|
||||
metric_list: List[Union[Optional[Metric], Optional['MetricGroup']]],
|
||||
metric_list: Sequence[Union[Optional[Metric], Optional['MetricGroup']]],
|
||||
description: Optional[str] = None):
|
||||
self.name = name
|
||||
self.metric_list = []
|
||||
|
|
@ -696,7 +692,7 @@ class MetricGroup:
|
|||
result.append(x.ToPerfJson())
|
||||
return result
|
||||
|
||||
def ToMetricGroupDescriptions(self, root: bool = True) -> Dict[str, str]:
|
||||
def ToMetricGroupDescriptions(self, _root: bool = True) -> Dict[str, str]:
|
||||
result = {self.name: self.description} if self.description else {}
|
||||
for x in self.metric_list:
|
||||
result.update(x.ToMetricGroupDescriptions(False))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user