Skip to content

Commit 56f38ec

Browse files
author
bench
committed
feat: enhance compare_metrics.py to support branch filtering and display
1 parent 47776f9 commit 56f38ec

1 file changed

Lines changed: 51 additions & 13 deletions

File tree

scripts/compare_metrics.py

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
#!/usr/bin/env python3
22
"""
3-
compare_metrics.py [--format {table|sparkline|html}]
3+
compare_metrics.py [--format {table|sparkline|html}] [--branch NAME]
44
55
Fetches bench_history.csv and size_history.csv from the metrics branch,
6-
groups by benchmark/metric name, and displays evolution over time.
6+
groups by benchmark/metric name, filters by branch, and displays evolution over time.
77
88
Output formats:
99
table - Simple ASCII table (default)
1010
sparkline - Compact sparkline visualization
1111
html - Interactive HTML report
12+
13+
Options:
14+
--branch NAME - Filter by git branch name (default: current branch)
1215
"""
1316

1417
import sys
@@ -43,6 +46,20 @@ def fetch_csv_from_branch(filename: str, branch: str = "metrics") -> List[Dict]:
4346
return []
4447

4548

49+
def get_current_branch() -> str:
50+
"""Get the current git branch name."""
51+
try:
52+
result = subprocess.run(
53+
["git", "rev-parse", "--abbrev-ref", "HEAD"],
54+
capture_output=True,
55+
text=True,
56+
check=True,
57+
)
58+
return result.stdout.strip()
59+
except subprocess.CalledProcessError:
60+
return "main"
61+
62+
4663
def parse_timestamp(ts: str) -> datetime:
4764
"""Parse ISO timestamp."""
4865
try:
@@ -51,12 +68,14 @@ def parse_timestamp(ts: str) -> datetime:
5168
return datetime.min
5269

5370

54-
def group_metrics(bench_rows: List[Dict], size_rows: List[Dict]) -> Dict[str, List[Dict]]:
55-
"""Group metrics by name (benchmark_name or metric_name) with timestamps."""
71+
def group_metrics(bench_rows: List[Dict], size_rows: List[Dict], branch: str = None) -> Dict[str, List[Dict]]:
72+
"""Group metrics by name, filtered by branch and sorted by timestamp."""
5673
groups = defaultdict(list)
5774

5875
# Group benchmarks
5976
for row in bench_rows:
77+
if branch and row.get("branch", "") != branch:
78+
continue
6079
name = row.get("benchmark_name", "").strip()
6180
if name:
6281
groups[f"bench/{name}"].append({
@@ -70,6 +89,8 @@ def group_metrics(bench_rows: List[Dict], size_rows: List[Dict]) -> Dict[str, Li
7089

7190
# Group file sizes
7291
for row in size_rows:
92+
if branch and row.get("branch", "") != branch:
93+
continue
7394
name = row.get("metric_name", "").strip()
7495
if name:
7596
groups[f"size/{name}"].append({
@@ -134,9 +155,11 @@ def sparkline(values: List[float], width: int = 10) -> str:
134155
return sparkline_str
135156

136157

137-
def display_table(groups: Dict[str, List[Dict]]) -> None:
158+
def display_table(groups: Dict[str, List[Dict]], branch: str = None) -> None:
138159
"""Display metrics as ASCII table."""
139160
print("\n" + "=" * 120)
161+
if branch:
162+
print(f"Metrics for branch: {branch}")
140163
print(f"{'Metric':<40} {'Latest':<20} {'Prev':<20} {'Change':<15} {'Trend':<20}")
141164
print("=" * 120)
142165

@@ -166,9 +189,11 @@ def display_table(groups: Dict[str, List[Dict]]) -> None:
166189
print("=" * 120)
167190

168191

169-
def display_sparkline(groups: Dict[str, List[Dict]]) -> None:
192+
def display_sparkline(groups: Dict[str, List[Dict]], branch: str = None) -> None:
170193
"""Display metrics with sparklines for compact view."""
171194
print("\n" + "─" * 100)
195+
if branch:
196+
print(f"Metrics for branch: {branch}")
172197
print(f"{'Metric':<45} {'Sparkline':<40} {'Latest':<15}")
173198
print("─" * 100)
174199

@@ -186,7 +211,7 @@ def display_sparkline(groups: Dict[str, List[Dict]]) -> None:
186211
print("─" * 100)
187212

188213

189-
def display_html(groups: Dict[str, List[Dict]], output_path: str = "metrics_report.html") -> None:
214+
def display_html(groups: Dict[str, List[Dict]], output_path: str = "metrics_report.html", branch: str = None) -> None:
190215
"""Generate an interactive HTML report (requires plotly)."""
191216
try:
192217
import plotly.graph_objects as go
@@ -226,8 +251,12 @@ def display_html(groups: Dict[str, List[Dict]], output_path: str = "metrics_repo
226251
col=col,
227252
)
228253

254+
title = "herkos Metrics Evolution"
255+
if branch:
256+
title += f" (branch: {branch})"
257+
229258
fig.update_layout(
230-
title_text="herkos Metrics Evolution",
259+
title_text=title,
231260
height=300 * ((num_metrics + 1) // 2),
232261
showlegend=False,
233262
)
@@ -251,9 +280,17 @@ def main() -> int:
251280
default="metrics_report.html",
252281
help="Output file for HTML format (default: metrics_report.html)",
253282
)
283+
parser.add_argument(
284+
"--branch",
285+
default=None,
286+
help="Filter metrics by branch name (default: current git branch)",
287+
)
254288

255289
args = parser.parse_args()
256290

291+
# Use current branch as default if not specified
292+
target_branch = args.branch or get_current_branch()
293+
257294
print("Fetching metrics from 'metrics' branch...")
258295
bench_rows = fetch_csv_from_branch("bench_history.csv")
259296
size_rows = fetch_csv_from_branch("size_history.csv")
@@ -263,19 +300,20 @@ def main() -> int:
263300
return 1
264301

265302
print(f" Loaded {len(bench_rows)} benchmark entries, {len(size_rows)} size entries")
303+
print(f" Filtering for branch: {target_branch}")
266304

267-
groups = group_metrics(bench_rows, size_rows)
305+
groups = group_metrics(bench_rows, size_rows, target_branch)
268306

269307
if not groups:
270-
print("No metrics found.", file=sys.stderr)
308+
print(f"No metrics found for branch '{target_branch}'.", file=sys.stderr)
271309
return 1
272310

273311
if args.format == "table":
274-
display_table(groups)
312+
display_table(groups, target_branch)
275313
elif args.format == "sparkline":
276-
display_sparkline(groups)
314+
display_sparkline(groups, target_branch)
277315
elif args.format == "html":
278-
display_html(groups, args.output)
316+
display_html(groups, args.output, target_branch)
279317

280318
return 0
281319

0 commit comments

Comments
 (0)