Skip to content

Commit 283df13

Browse files
committed
json -> toml
1 parent ed93422 commit 283df13

4 files changed

Lines changed: 77 additions & 39 deletions

File tree

.github/benchmark-tracking.json

Lines changed: 0 additions & 11 deletions
This file was deleted.

.github/benchmark-tracking.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
default_threshold_percent = 10.0
2+
3+
[[benchmarks]]
4+
package = "commonware-storage"
5+
bench = "qmdb"
6+
cargo_flags = ["--features", "test-traits"]
7+
name = "qmdb::merkleize/variant=any::unordered::fixed::mmr keys=10000 ch=false sync=false"

.github/scripts/benchmark-tracking.py

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
"""Run exact Criterion benchmarks and compare them with a main-branch artifact."""
33

44
import argparse
5-
import json
65
import os
76
import re
87
import shlex
98
import subprocess
109
import sys
10+
import tomllib
1111
from pathlib import Path
1212
from typing import Any
1313

@@ -18,11 +18,11 @@
1818

1919
def parse_args() -> argparse.Namespace:
2020
parser = argparse.ArgumentParser(description=__doc__)
21-
parser.add_argument("--config", required=True, help="Path to benchmark tracking config JSON")
21+
parser.add_argument("--config", required=True, help="Path to benchmark tracking config TOML")
2222
parser.add_argument("--output-dir", required=True, help="Directory for result artifacts")
2323
parser.add_argument(
2424
"--baseline",
25-
help="Path to a previous benchmark-tracking current.json artifact from main",
25+
help="Path to a previous benchmark-tracking current.toml artifact from main",
2626
)
2727
parser.add_argument(
2828
"--skip-run",
@@ -32,9 +32,9 @@ def parse_args() -> argparse.Namespace:
3232
return parser.parse_args()
3333

3434

35-
def read_json(path: Path) -> dict[str, Any]:
36-
with path.open("r", encoding="utf-8") as f:
37-
return json.load(f)
35+
def read_toml(path: Path) -> dict[str, Any]:
36+
with path.open("rb") as f:
37+
return tomllib.load(f)
3838

3939

4040
def validate_config(config: dict[str, Any]) -> list[dict[str, Any]]:
@@ -164,10 +164,9 @@ def load_baseline(path: str | None) -> list[dict[str, Any]] | None:
164164
baseline_path = Path(path)
165165
if not baseline_path.exists():
166166
return None
167-
with baseline_path.open("r", encoding="utf-8") as f:
168-
baseline = json.load(f)
167+
baseline = read_toml(baseline_path).get("benchmarks")
169168
if not isinstance(baseline, list):
170-
raise ValueError(f"baseline `{path}` must contain a JSON array")
169+
raise ValueError(f"baseline `{path}` must contain a `benchmarks` array")
171170
return baseline
172171

173172

@@ -200,6 +199,56 @@ def escape_cell(value: str) -> str:
200199
return value.replace("|", "\\|").replace("\n", "<br>")
201200

202201

202+
def toml_quote(value: str) -> str:
203+
escaped = value.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n")
204+
return f'"{escaped}"'
205+
206+
207+
def toml_value(value: Any) -> str:
208+
if isinstance(value, bool):
209+
return "true" if value else "false"
210+
if isinstance(value, int | float):
211+
return str(value)
212+
if isinstance(value, str):
213+
return toml_quote(value)
214+
if isinstance(value, list):
215+
return "[" + ", ".join(toml_value(item) for item in value) + "]"
216+
raise TypeError(f"unsupported TOML value: {value!r}")
217+
218+
219+
def write_toml_table(path: Path, values: dict[str, Any]) -> None:
220+
lines = []
221+
for key, value in values.items():
222+
if value is None:
223+
continue
224+
lines.append(f"{key} = {toml_value(value)}")
225+
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
226+
227+
228+
def append_toml_values(lines: list[str], values: dict[str, Any], prefix: str) -> None:
229+
nested = []
230+
for key, value in values.items():
231+
if value is None:
232+
continue
233+
if isinstance(value, dict):
234+
nested.append((key, value))
235+
else:
236+
lines.append(f"{key} = {toml_value(value)}")
237+
for key, value in nested:
238+
lines.extend(["", f"[{prefix}.{key}]"])
239+
append_toml_values(lines, value, f"{prefix}.{key}")
240+
241+
242+
def write_toml_array(path: Path, name: str, values: list[dict[str, Any]]) -> None:
243+
lines = []
244+
for value in values:
245+
if lines:
246+
lines.append("")
247+
lines.append(f"[[{name}]]")
248+
append_toml_values(lines, value, name)
249+
path.write_text("\n".join(lines) + "\n", encoding="utf-8")
250+
251+
203252
def compare_results(
204253
current: list[dict[str, Any]], baseline_data: list[dict[str, Any]] | None
205254
) -> list[dict[str, Any]]:
@@ -301,7 +350,7 @@ def main() -> int:
301350
output_dir = Path(args.output_dir)
302351
output_dir.mkdir(parents=True, exist_ok=True)
303352

304-
config = read_json(config_path)
353+
config = read_toml(config_path)
305354
benchmarks = validate_config(config)
306355

307356
if args.skip_run:
@@ -335,14 +384,13 @@ def main() -> int:
335384
"missing_baseline_count": missing_count,
336385
}
337386

338-
(output_dir / "current.json").write_text(json.dumps(current, indent=2) + "\n", encoding="utf-8")
339-
(output_dir / "comparison.json").write_text(
340-
json.dumps(comparisons, indent=2) + "\n", encoding="utf-8"
341-
)
342-
(output_dir / "summary.json").write_text(json.dumps(summary, indent=2) + "\n", encoding="utf-8")
387+
write_toml_array(output_dir / "current.toml", "benchmarks", current)
388+
write_toml_array(output_dir / "comparison.toml", "comparisons", comparisons)
389+
write_toml_table(output_dir / "summary.toml", summary)
343390
(output_dir / "comment.md").write_text(render_markdown(comparisons), encoding="utf-8")
344391

345-
print(json.dumps(summary, indent=2))
392+
for key, value in summary.items():
393+
print(f"{key}: {value}")
346394
return 0
347395

348396

.github/workflows/benchmark-tracking.yml

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@ on:
55
branches: [main]
66
pull_request:
77
types: [opened, synchronize, reopened, ready_for_review]
8-
workflow_dispatch:
9-
inputs:
10-
config:
11-
description: Path to the benchmark tracking config JSON
12-
required: false
13-
default: .github/benchmark-tracking.json
148

159
permissions:
1610
actions: read
@@ -29,7 +23,7 @@ jobs:
2923
runs-on: ubuntu-latest-8
3024
timeout-minutes: 180
3125
env:
32-
BENCHMARK_TRACKING_CONFIG: ${{ github.event.inputs.config || '.github/benchmark-tracking.json' }}
26+
BENCHMARK_TRACKING_CONFIG: .github/benchmark-tracking.toml
3327
steps:
3428
- name: Checkout
3529
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
@@ -89,8 +83,8 @@ jobs:
8983
id: run
9084
run: |
9185
baseline_args=()
92-
if [ -f benchmark-tracking-baseline/current.json ]; then
93-
baseline_args=(--baseline benchmark-tracking-baseline/current.json)
86+
if [ -f benchmark-tracking-baseline/current.toml ]; then
87+
baseline_args=(--baseline benchmark-tracking-baseline/current.toml)
9488
fi
9589
python3 .github/scripts/benchmark-tracking.py \
9690
--config "$BENCHMARK_TRACKING_CONFIG" \
@@ -143,11 +137,11 @@ jobs:
143137
if: always() && github.event_name == 'pull_request' && steps.run.outcome == 'success'
144138
run: |
145139
python3 - <<'PY'
146-
import json
147140
import sys
141+
import tomllib
148142
149-
with open('benchmark-tracking-results/summary.json', encoding='utf-8') as f:
150-
summary = json.load(f)
143+
with open('benchmark-tracking-results/summary.toml', 'rb') as f:
144+
summary = tomllib.load(f)
151145
regressions = summary.get('regression_count', 0)
152146
if regressions:
153147
print(f'{regressions} benchmark(s) exceeded the configured threshold')

0 commit comments

Comments
 (0)