From 391ff0891f61f36f6e0a8384027e552876e815e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 6 Oct 2026 06:45:50 +0000 Subject: [PATCH] Apply remaining changes Co-authored-by: embtom <16663460+embtom@users.noreply.github.com> --- .github/workflows/benchmark.yml | 16 +++++++++ README.md | 3 ++ scripts/benchmark-comparison.py | 58 +++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100755 scripts/benchmark-comparison.py diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 6f57d78..3e18714 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -41,3 +41,19 @@ jobs: gh-pages-branch: gh-pages benchmark-data-dir-path: . auto-push: true + + - name: Render snprintf vs ctprintf comparison + run: | + python3 scripts/benchmark-comparison.py \ + ctprintf/build/benchmark/benchmarks/benchmark_results.json \ + /tmp/comparison.html "$GITHUB_STEP_SUMMARY" + + - name: Publish comparison page + run: | + git fetch origin gh-pages + git checkout -f gh-pages + cp /tmp/comparison.html comparison.html + git add comparison.html + git -c user.name=github-actions -c user.email=github-actions@github.com \ + commit -m "Update snprintf vs ctprintf comparison" || exit 0 + git push origin gh-pages diff --git a/README.md b/README.md index 01882f8..139c8b6 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,9 @@ over time. Results are updated on pushes to `main` and weekly. To publish the dashboard, enable GitHub Pages for the repository with the `gh-pages` branch as the source. +A direct side-by-side [snprintf vs ctprintf comparison](https://embtom.github.io/ctprintf/comparison.html) +is generated from the same run by `scripts/benchmark-comparison.py`. + ## Creating a package CPack creates a gzip-compressed tarball containing the installable headers, diff --git a/scripts/benchmark-comparison.py b/scripts/benchmark-comparison.py new file mode 100755 index 0000000..54368eb --- /dev/null +++ b/scripts/benchmark-comparison.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Render a direct snprintf vs ctprintf comparison from Google Benchmark JSON. + +Usage: benchmark-comparison.py results.json output.html [summary.md] +""" +import html +import json +import sys +from collections import defaultdict + + +def load(path): + with open(path) as f: + data = json.load(f) + times = defaultdict(dict) + for b in data["benchmarks"]: + if b.get("run_type") == "aggregate" and b.get("aggregate_name") != "mean": + continue + name = b.get("run_name", b["name"]) + _, impl, case = name.split("_", 2) + times[case][impl] = (b["cpu_time"], b.get("time_unit", "ns")) + return {c: v for c, v in times.items() if "snprintf" in v and "ctprintf" in v} + + +def main(): + cases = load(sys.argv[1]) + rows = [] + for case, v in sorted(cases.items()): + s, unit = v["snprintf"] + c, _ = v["ctprintf"] + rows.append((case, s, c, unit, s / c)) + + md = ["| Case | snprintf | ctprintf | speedup |", "|---|---|---|---|"] + for case, s, c, unit, r in rows: + md.append(f"| {case} | {s:.1f} {unit} | {c:.1f} {unit} | {r:.2f}x |") + if len(sys.argv) > 3: + with open(sys.argv[3], "a") as f: + f.write("## snprintf vs ctprintf\n\n" + "\n".join(md) + "\n") + + body = [] + for case, s, c, unit, r in rows: + m = max(s, c) + body.append( + f"

{html.escape(case)} ({r:.2f}x {'faster' if r >= 1 else 'slower'})

" + f"
snprintf {s:.1f} {unit}
" + f"
ctprintf {c:.1f} {unit}
" + ) + page = f"""snprintf vs ctprintf + +

snprintf vs ctprintf

Lower is better (CPU time per call). +History dashboard

{''.join(body)}""" + with open(sys.argv[2], "w") as f: + f.write(page) + + +main()