Skip to content

Commit 6c187f5

Browse files
tenpercentclaude
andcommitted
Add copyright header and format with ruff
- Add AMD copyright header and MIT license identifier - Format code with ruff for consistent style - Remove unused pathlib.Path import - Convert single quotes to double quotes - Fix line wrapping and indentation per ruff style All ruff checks now pass without errors. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 8fcf159 commit 6c187f5

1 file changed

Lines changed: 113 additions & 87 deletions

File tree

Lines changed: 113 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#!/usr/bin/env python3
2+
# Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
3+
# SPDX-License-Identifier: MIT
4+
25
# /// script
36
# requires-python = ">=3.8"
47
# dependencies = [
@@ -17,7 +20,6 @@
1720
import sys
1821
from collections import defaultdict
1922
from datetime import datetime
20-
from pathlib import Path
2123

2224
try:
2325
from jinja2 import Environment, FileSystemLoader
@@ -31,119 +33,143 @@
3133
def parse_arguments():
3234
"""Parse command-line arguments."""
3335
if len(sys.argv) < 7:
34-
print("Usage: analyze_build_trace.py <trace_file> <output_file> <target> <granularity> <build_time> <template_dir>")
36+
print(
37+
"Usage: analyze_build_trace.py <trace_file> <output_file> <target> <granularity> <build_time> <template_dir>"
38+
)
3539
sys.exit(1)
3640

3741
return {
38-
'trace_file': sys.argv[1],
39-
'output_file': sys.argv[2],
40-
'target': sys.argv[3],
41-
'granularity': sys.argv[4],
42-
'build_time': sys.argv[5],
43-
'template_dir': sys.argv[6],
42+
"trace_file": sys.argv[1],
43+
"output_file": sys.argv[2],
44+
"target": sys.argv[3],
45+
"granularity": sys.argv[4],
46+
"build_time": sys.argv[5],
47+
"template_dir": sys.argv[6],
4448
}
4549

4650

4751
def load_trace_data(trace_file):
4852
"""Load and parse the trace JSON file."""
49-
print(f'Loading trace file: {trace_file}')
50-
with open(trace_file, 'r') as f:
53+
print(f"Loading trace file: {trace_file}")
54+
with open(trace_file, "r") as f:
5155
return json.load(f)
5256

5357

5458
def process_events(data):
5559
"""Process trace events and extract template instantiation statistics."""
56-
print('Processing events...')
60+
print("Processing events...")
5761

58-
template_stats = defaultdict(lambda: {'count': 0, 'total_dur': 0})
62+
template_stats = defaultdict(lambda: {"count": 0, "total_dur": 0})
5963
phase_stats = defaultdict(int)
6064
top_individual = []
6165

62-
for event in data.get('traceEvents', []):
63-
name = event.get('name', '')
64-
dur = int(event.get('dur', 0)) # Keep as integer microseconds
66+
for event in data.get("traceEvents", []):
67+
name = event.get("name", "")
68+
dur = int(event.get("dur", 0)) # Keep as integer microseconds
6569

6670
if name and dur > 0:
6771
phase_stats[name] += dur
6872

69-
if name in ['InstantiateFunction', 'InstantiateClass']:
70-
detail = event.get('args', {}).get('detail', '')
71-
top_individual.append({
72-
'detail': detail,
73-
'dur': dur,
74-
'type': name
75-
})
73+
if name in ["InstantiateFunction", "InstantiateClass"]:
74+
detail = event.get("args", {}).get("detail", "")
75+
top_individual.append({"detail": detail, "dur": dur, "type": name})
7676

7777
# Extract template name (everything before '<' or '(')
78-
match = re.match(r'^([^<(]+)', detail)
78+
match = re.match(r"^([^<(]+)", detail)
7979
if match:
8080
template_name = match.group(1).strip()
8181
# Normalize template names
82-
template_name = re.sub(r'^ck::', '', template_name)
83-
template_name = re.sub(r'^std::', 'std::', template_name)
82+
template_name = re.sub(r"^ck::", "", template_name)
83+
template_name = re.sub(r"^std::", "std::", template_name)
8484

85-
template_stats[template_name]['count'] += 1
86-
template_stats[template_name]['total_dur'] += dur
85+
template_stats[template_name]["count"] += 1
86+
template_stats[template_name]["total_dur"] += dur
8787

8888
return template_stats, phase_stats, top_individual
8989

9090

9191
def prepare_template_data(template_stats, phase_stats, top_individual):
9292
"""Prepare and calculate derived statistics for template rendering."""
93-
print('Sorting data...')
93+
print("Sorting data...")
9494

9595
# Sort data
9696
sorted_phases = sorted(phase_stats.items(), key=lambda x: x[1], reverse=True)
97-
top_individual.sort(key=lambda x: x['dur'], reverse=True)
97+
top_individual.sort(key=lambda x: x["dur"], reverse=True)
9898

9999
# Calculate totals
100-
total_template_time = sum(s['total_dur'] for s in template_stats.values())
100+
total_template_time = sum(s["total_dur"] for s in template_stats.values())
101101
total_trace_time = sum(phase_stats.values())
102-
total_inst = sum(s['count'] for s in template_stats.values())
102+
total_inst = sum(s["count"] for s in template_stats.values())
103103

104104
# Prepare templates by time with calculated fields
105105
templates_by_time = []
106-
for name, stats in sorted(template_stats.items(), key=lambda x: x[1]['total_dur'], reverse=True):
107-
templates_by_time.append((name, {
108-
'count': stats['count'],
109-
'total_dur': stats['total_dur'],
110-
'avg': stats['total_dur'] // stats['count'] if stats['count'] > 0 else 0,
111-
'pct': 100 * stats['total_dur'] / total_template_time if total_template_time > 0 else 0
112-
}))
106+
for name, stats in sorted(
107+
template_stats.items(), key=lambda x: x[1]["total_dur"], reverse=True
108+
):
109+
templates_by_time.append(
110+
(
111+
name,
112+
{
113+
"count": stats["count"],
114+
"total_dur": stats["total_dur"],
115+
"avg": stats["total_dur"] // stats["count"]
116+
if stats["count"] > 0
117+
else 0,
118+
"pct": 100 * stats["total_dur"] / total_template_time
119+
if total_template_time > 0
120+
else 0,
121+
},
122+
)
123+
)
113124

114125
# Prepare templates by count
115126
templates_by_count = []
116-
for name, stats in sorted(template_stats.items(), key=lambda x: x[1]['count'], reverse=True):
117-
templates_by_count.append((name, {
118-
'count': stats['count'],
119-
'total_dur': stats['total_dur'],
120-
'avg': stats['total_dur'] // stats['count'] if stats['count'] > 0 else 0
121-
}))
127+
for name, stats in sorted(
128+
template_stats.items(), key=lambda x: x[1]["count"], reverse=True
129+
):
130+
templates_by_count.append(
131+
(
132+
name,
133+
{
134+
"count": stats["count"],
135+
"total_dur": stats["total_dur"],
136+
"avg": stats["total_dur"] // stats["count"]
137+
if stats["count"] > 0
138+
else 0,
139+
},
140+
)
141+
)
122142

123143
# Add friendly type names to individual instantiations
124144
for inst in top_individual:
125-
inst['inst_type'] = 'Func' if inst['type'] == 'InstantiateFunction' else 'Class'
145+
inst["inst_type"] = "Func" if inst["type"] == "InstantiateFunction" else "Class"
126146

127147
# Calculate additional metrics
128148
median_count = 0
129149
if len(template_stats) > 0:
130-
median_count = sorted([s["count"] for s in template_stats.values()])[len(template_stats) // 2]
150+
median_count = sorted([s["count"] for s in template_stats.values()])[
151+
len(template_stats) // 2
152+
]
131153

132154
top10_pct = 0
133155
if len(templates_by_time) >= 10:
134-
top10_pct = 100 * sum(s[1]["total_dur"] for s in templates_by_time[:10]) / total_template_time
156+
top10_pct = (
157+
100
158+
* sum(s[1]["total_dur"] for s in templates_by_time[:10])
159+
/ total_template_time
160+
)
135161

136162
return {
137-
'sorted_phases': sorted_phases,
138-
'top_individual': top_individual,
139-
'templates_by_time': templates_by_time,
140-
'templates_by_count': templates_by_count,
141-
'total_template_time': total_template_time,
142-
'total_trace_time': total_trace_time,
143-
'total_inst': total_inst,
144-
'median_count': median_count,
145-
'top10_pct': top10_pct,
146-
'unique_families': len(template_stats),
163+
"sorted_phases": sorted_phases,
164+
"top_individual": top_individual,
165+
"templates_by_time": templates_by_time,
166+
"templates_by_count": templates_by_count,
167+
"total_template_time": total_template_time,
168+
"total_trace_time": total_trace_time,
169+
"total_inst": total_inst,
170+
"median_count": median_count,
171+
"top10_pct": top10_pct,
172+
"unique_families": len(template_stats),
147173
}
148174

149175

@@ -153,17 +179,17 @@ def setup_jinja_environment(template_dir):
153179

154180
def format_number(value):
155181
"""Format number with thousand separators."""
156-
return f'{value:,}'
182+
return f"{value:,}"
157183

158184
def truncate(value, length):
159185
"""Truncate string to length with ellipsis."""
160186
if len(value) > length:
161-
return value[:length - 3] + '...'
187+
return value[: length - 3] + "..."
162188
return value
163189

164190
def pad(value, length):
165191
"""Pad string to specified length."""
166-
return f'{value:<{length}}'
192+
return f"{value:<{length}}"
167193

168194
def us_to_ms(value):
169195
"""Convert microseconds to milliseconds."""
@@ -173,37 +199,37 @@ def us_to_s(value):
173199
"""Convert microseconds to seconds."""
174200
return value / 1000000.0
175201

176-
env.filters['format_number'] = format_number
177-
env.filters['truncate'] = truncate
178-
env.filters['pad'] = pad
179-
env.filters['us_to_ms'] = us_to_ms
180-
env.filters['us_to_s'] = us_to_s
202+
env.filters["format_number"] = format_number
203+
env.filters["truncate"] = truncate
204+
env.filters["pad"] = pad
205+
env.filters["us_to_ms"] = us_to_ms
206+
env.filters["us_to_s"] = us_to_s
181207

182208
return env
183209

184210

185211
def generate_report(env, data, args, total_events):
186212
"""Generate the final report using Jinja2 template."""
187-
print('Rendering report with Jinja2...')
213+
print("Rendering report with Jinja2...")
188214

189-
template = env.get_template('build_analysis_report.md.jinja')
215+
template = env.get_template("build_analysis_report.md.jinja")
190216

191217
report_content = template.render(
192218
timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
193-
target=args['target'],
194-
granularity=args['granularity'],
195-
build_time=args['build_time'],
219+
target=args["target"],
220+
granularity=args["granularity"],
221+
build_time=args["build_time"],
196222
total_events=total_events,
197-
total_instantiations=data['total_inst'],
198-
unique_families=data['unique_families'],
199-
total_trace_time=data['total_trace_time'],
200-
total_template_time=data['total_template_time'],
201-
phases=data['sorted_phases'],
202-
top_individual=data['top_individual'],
203-
templates_by_time=data['templates_by_time'],
204-
templates_by_count=data['templates_by_count'],
205-
median_count=data['median_count'],
206-
top10_pct=data['top10_pct']
223+
total_instantiations=data["total_inst"],
224+
unique_families=data["unique_families"],
225+
total_trace_time=data["total_trace_time"],
226+
total_template_time=data["total_template_time"],
227+
phases=data["sorted_phases"],
228+
top_individual=data["top_individual"],
229+
templates_by_time=data["templates_by_time"],
230+
templates_by_count=data["templates_by_count"],
231+
median_count=data["median_count"],
232+
top10_pct=data["top10_pct"],
207233
)
208234

209235
return report_content
@@ -214,8 +240,8 @@ def main():
214240
args = parse_arguments()
215241

216242
# Load trace data
217-
trace_data = load_trace_data(args['trace_file'])
218-
total_events = len(trace_data.get('traceEvents', []))
243+
trace_data = load_trace_data(args["trace_file"])
244+
total_events = len(trace_data.get("traceEvents", []))
219245

220246
# Process events
221247
template_stats, phase_stats, top_individual = process_events(trace_data)
@@ -224,18 +250,18 @@ def main():
224250
data = prepare_template_data(template_stats, phase_stats, top_individual)
225251

226252
# Setup Jinja2 environment
227-
env = setup_jinja_environment(args['template_dir'])
253+
env = setup_jinja_environment(args["template_dir"])
228254

229255
# Generate report
230256
report_content = generate_report(env, data, args, total_events)
231257

232258
# Write output
233-
with open(args['output_file'], 'w') as f:
259+
with open(args["output_file"], "w") as f:
234260
f.write(report_content)
235261

236-
print(f'Report generated: {args["output_file"]}')
237-
print(f'Report size: {len(report_content)} bytes')
262+
print(f"Report generated: {args['output_file']}")
263+
print(f"Report size: {len(report_content)} bytes")
238264

239265

240-
if __name__ == '__main__':
266+
if __name__ == "__main__":
241267
main()

0 commit comments

Comments
 (0)