-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathperfmonmetrics2perfspect.py
executable file
·131 lines (117 loc) · 4.5 KB
/
perfmonmetrics2perfspect.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python3
# perfmonmetrics2perfspect.py - converts a metrics file to the YAML file format used by PerfSpect 3.0+.
#
# The input metrics file can be one of the following:
# - perfmon metrics json file from github.com/intel/perfmon
# - xml file from perfmon.intel.com or EMON/EDP release
#
# Usage: perfmonmetrics2perfspect.py <metric file>
#
# New metrics file in perfspect format is printed to stdout.
# Copyright (C) 2021-2024 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
import sys
import json
import xml.etree.ElementTree as ET
def replace_vars_in_formula(vars, formula):
varMap = {
"[INST_RETIRED.ANY]": "[instructions]",
"[CPU_CLK_UNHALTED.THREAD]": "[cpu-cycles]",
"[CPU_CLK_UNHALTED.REF]": "[ref-cycles]",
"[CPU_CLK_UNHALTED.REF_TSC]": "[ref-cycles]",
"DURATIONTIMEINSECONDS": "1",
"[DURATIONTIMEINMILLISECONDS]": "1000",
"[TOPDOWN.SLOTS:perf_metrics]": "[TOPDOWN.SLOTS]",
"[OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD:c4]": "[OFFCORE_REQUESTS_OUTSTANDING.DATA_RD:c4]",
"[system.tsc_freq]": "[SYSTEM_TSC_FREQ]",
"[system.cha_count/system.socket_count]": "[CHAS_PER_SOCKET]",
"[system.socket_count]": "[SOCKET_COUNT]",
}
newFormula = ""
i = 0
while i < len(formula):
if formula[i].isalpha() or formula[i] == "_":
x = formula[i]
k = i + 1
while k < len(formula) and (formula[k].isalpha() or formula[k] == "_"):
x += formula[k]
k += 1
if vars.get(x) is not None:
newFormula = newFormula + "[" + vars[x] + "]"
else:
newFormula = newFormula + formula[i:k]
i = k
else:
newFormula += formula[i]
i += 1
for v in varMap:
newFormula = newFormula.replace(v, varMap[v])
return newFormula
def translate_perfmon_json_metrics_to_perfspect(inFile):
with open(inFile, "r") as f:
mf = json.load(f)
if mf.get("Metrics") is None:
print(f"ERROR: No metrics were found in {inFile}", file=sys.stderr)
return
print(f"Metrics in {inFile}: {len(mf['Metrics'])}", file=sys.stderr)
vars = {}
result = []
for m in mf["Metrics"]:
vars.clear()
metric = {}
metric["name"] = m["LegacyName"]
# extract the events and constants
for e in m["Events"]:
vars[e["Alias"]] = e["Name"]
for c in m["Constants"]:
vars[c["Alias"]] = c["Name"]
# convert the formula
metric["expression"] = replace_vars_in_formula(vars, m["Formula"])
result.append(metric)
return result
# this function has the following known limitations:
# - it does not convert the max notation, e.g., [(val1), (val2)].max
# - it does not convert the list index notation, e.g., val[0][0]
def translate_perfmon_xml_metrics_to_perfspect(inFile):
tree = ET.parse(inFile)
root = tree.getroot()
vars = {}
result = []
for m in root:
vars.clear()
metric = {}
metric["name"] = m.attrib["name"]
# extract the events and constants
for e in m.findall("event"):
vars[e.attrib["alias"]] = e.text
for c in m.findall("constant"):
vars[c.attrib["alias"]] = c.text
# convert the formula
formula = m.find("formula").text
metric["expression"] = replace_vars_in_formula(vars, formula)
result.append(metric)
return result
# translate perfmon metrics file to perfspect style metrics file
# inFile - perfmon_metrics.json file
def translate_perfmon_metrics_to_perfspect(inFile):
# the file can be either a json file or an xml file
fileType = inFile.split(".")[-1]
if fileType == "json":
result = translate_perfmon_json_metrics_to_perfspect(inFile)
elif fileType == "xml":
result = translate_perfmon_xml_metrics_to_perfspect(inFile)
else:
print(f"ERROR: Unsupported file type {fileType}", file=sys.stderr)
return
print(f"Generated metrics: {len(result)}", file=sys.stderr)
json_object = json.dumps(result, indent=4)
print(json_object)
# arg1 - perfmon metrics json file from github.com/intel/perfmon or xml file from perfmon.intel.com or EMON/EDP release
if __name__ == "__main__":
if len(sys.argv) != 2:
print(
"Usage: perfmonmetrics2perfspect.py <perfmon metric json or xml file>",
file=sys.stderr,
)
sys.exit(1)
translate_perfmon_metrics_to_perfspect(sys.argv[1])