Skip to content

perf(ci): build Rust coverage as a Nix derivation - #1266

Merged
ryoppippi merged 2 commits into
mainfrom
ci/nixify-rust-coverage
Jun 11, 2026
Merged

ryoppippi merged 2 commits into
mainfrom
ci/nixify-rust-coverage

Conversation

@ryoppippi

@ryoppippi ryoppippi commented Jun 11, 2026 •

Copy link
Copy Markdown
Member

Summary

Moves the Rust coverage report from a dev-shell cargo llvm-cov invocation
to a crane cargoLlvmCov Nix package, so it shares the warm cargoArtifacts
cache instead of recompiling the whole workspace cold on every CI run.

What changed

  • nix/coverage.nix (new): a ccusage-coverage package built with crane's
    cargoLlvmCov, reusing the shared cargoArtifacts closure and emitting the
    cobertura report directly at $out. A preBuild seeds the empty Claude data
    directories under a writable $HOME, since the build sandbox has none.
  • flake.nix: import the new module.
  • .github/workflows/ci.yaml: the coverage step now nix builds the
    package and copies its report, replacing the nix develop --command cargo llvm-cov call.

Why

cargo llvm-cov compiled the entire workspace into rust/target, but only
/nix is persisted on the per-job Blacksmith sticky disk, so that target dir
was never cached. It was the one Rust compile that stayed cold on every run.
As a Nix derivation the dependencies stay warm on the sticky disk, and an
unchanged source tree returns the cached report instantly — bringing coverage
onto the same crane caching path as the rest of the Rust builds.

Testing

  • nix build .#ccusage-coverage locally (aarch64-darwin): all workspace tests
    pass in the sandbox and a valid cobertura XML is produced (line-rate 77.4%).
  • Re-build with unchanged sources is a cache hit (~0.4s, no recompile).

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Build Rust coverage as a Nix derivation using crane to reuse the shared cargoArtifacts cache, eliminating cold rebuilds and speeding up CI. CI now builds ccusage-coverage and uploads its Cobertura report.

  • Refactors

    • Added nix/coverage.nix defining ccusage-coverage via crane.cargoLlvmCov; reuses cargoArtifacts, writes Cobertura to $out, and seeds a writable $HOME for tests.
    • Imported the module in flake.nix.
    • CI: replaced dev-shell cargo llvm-cov with nix build .#ccusage-coverage and copy the report.
  • Bug Fixes

    • Provided TZDIR from nixpkgs tzdata in the coverage build so timezone-dependent tests resolve real offsets in the hermetic sandbox.

Written for commit 16f8a74. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Chores
    • Switched CI coverage generation to a Nix-built coverage package for more consistent, reproducible coverage artifacts.
    • Added a Nix coverage module to produce Cobertura XML and integrated it into the project’s Nix configuration.
    • Improved build/test stability (avoids timezone-dependent shifts and ensures predictable build environment) to reduce flaky coverage results.

The coverage step ran `cargo llvm-cov` inside the dev shell, compiling the
whole workspace into `rust/target` on every CI run. Only `/nix` is kept on
the per-job Blacksmith sticky disk, so this target dir was never cached and
the coverage build was the one Rust compile that stayed cold each run.

Move it into a crane `cargoLlvmCov` package (`ccusage-coverage`) that reuses
the shared `cargoArtifacts` closure, so the deps stay warm on the sticky disk
and an unchanged source tree returns the cached cobertura report instantly.
CI now `nix build`s the package and copies its `$out` report. The build
sandbox has no $HOME, so a preBuild seeds the empty Claude data directories
the workspace tests resolve, matching what the dev-shell test job created.
@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a Nix module that builds Rust coverage as a package, imports it into the flake, and changes the CI test job to build .#ccusage-coverage and copy its Cobertura XML output to coverage/cobertura.xml.

Changes

Rust Coverage as Nix Package

Layer / File(s) Summary
Coverage derivation package
nix/coverage.nix
Nix module establishes per-system setup with the Rust overlay, reuses cargo caches, filters source tree, and defines packages.ccusage-coverage using craneLib.cargoLlvmCov (workspace, Cobertura XML output). Adds TZDIR for hermetic tests and a preBuild that seeds a writable HOME with Claude project/config directories.
Wire coverage module into flake
flake.nix
Adds ./nix/coverage.nix to flake-parts imports to expose the coverage derivation as a named package.
Update CI workflow to use coverage package
.github/workflows/ci.yaml
Test job switches from running cargo llvm-cov inside nix develop to nix build .#ccusage-coverage and copies the produced Cobertura XML into coverage/cobertura.xml.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ccusage/ccusage#1254: Both PRs modify the CI workflow's Rust coverage step; this PR introduces a dedicated Nix package for the coverage artifact.

Poem

I’m a rabbit in the build log, hopping light and merry,
I tuck coverage in Nix crates, neat as any berry,
From workspace builds to Cobertura gleam,
CI finds the file and wakes the testing stream. 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'perf(ci): build Rust coverage as a Nix derivation' accurately describes the main change: moving Rust coverage generation from a shell command to a Nix package derivation for better caching and CI performance.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/nixify-rust-coverage

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ccusage-guide 16f8a74 Commit Preview URL

Branch Preview URL
Jun 11 2026, 02:36 PM

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — moves Rust coverage from a dev-shell cargo llvm-cov invocation to a crane cargoLlvmCov Nix derivation, so it shares the warm cargoArtifacts cache instead of recompiling the whole workspace cold on every CI run.

  • New nix/coverage.nix — defines ccusage-coverage via craneLib.cargoLlvmCov, reusing cargoArtifacts and commonArgs from the existing ccusage package's passthru. Uses nix-filter to exclude noise (node_modules, target, dist, coverage), sets sourceRoot = "source/rust" to scope cargo to the workspace, and seeds a writable $HOME in preBuild for test sandbox requirements.
  • flake.nix import — adds ./nix/coverage.nix to the flake-parts import list.
  • CI workflow swap — replaces env -u CFLAGS -u CXXFLAGS nix develop --command cargo llvm-cov with nix build .#ccusage-coverage --print-build-logs --out-link "$RUNNER_TEMP/coverage-report" followed by a cp to stage the cobertura XML for upload.

Pullfrog  | View workflow run | Using Big Pickle (free via Pullfrog for OSS) | 𝕏

@pkg-pr-new

pkg-pr-new Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

ccusage

npx https://pkg.pr.new/ccusage@1266

@ccusage/ccusage-darwin-arm64

npx https://pkg.pr.new/@ccusage/ccusage-darwin-arm64@1266

@ccusage/ccusage-linux-arm64

npx https://pkg.pr.new/@ccusage/ccusage-linux-arm64@1266

@ccusage/ccusage-linux-x64

npx https://pkg.pr.new/@ccusage/ccusage-linux-x64@1266

@ccusage/ccusage-win32-x64

npx https://pkg.pr.new/@ccusage/ccusage-win32-x64@1266

commit: 16f8a74

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: c92100877586
Base SHA: ad1215f86a3c

This compares the Rust PR release binary against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new ad1215f86a3c 1.304s 615.3ms 58.1ms 3
PR pkg.pr.new c921008 1.015s 922.2ms 59.0ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: ad1215f86a3c; PR package: c921008. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 954.4ms 910.1ms 1.05x 725.00 MiB 725.25 MiB 1.00x 1.05 GiB/s 1.11 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 195.6ms 197.0ms 0.99x 90.00 MiB 93.00 MiB 1.03x 5.15 GiB/s 5.11 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 909.7ms 1.11 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 928.2ms 1.08 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 192.4ms 5.23 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 141.0ms 7.14 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 47.1ms 6.5ms 7.29x 43.00 MiB 3.00 MiB 0.07x 0.03 MiB/s 0.24 MiB/s
claude session --offline --json 0.00 MiB 46.2ms 6.3ms 7.37x 43.00 MiB 2.75 MiB 0.06x 0.03 MiB/s 0.25 MiB/s
codex daily --offline --json 0.00 MiB 45.3ms 5.6ms 8.08x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.15 MiB/s
codex session --offline --json 0.00 MiB 46.1ms 5.6ms 8.17x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.15 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 840.3ms 861.4ms 0.98x 730.00 MiB 734.00 MiB 1.01x 1.20 GiB/s 1.17 GiB/s
codex --offline --json 1.01 GiB 177.2ms 141.6ms 1.25x 85.75 MiB 92.00 MiB 1.07x 5.68 GiB/s 7.11 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.32 KiB 17.32 KiB +0.00 KiB 1.00x
installed native package binary 3324.77 KiB 3324.77 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: c92100877586
Base SHA: ad1215f86a3c

This compares the PR package against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new ad1215f86a3c 721.0ms 694.8ms 58.0ms 3
PR pkg.pr.new c921008 972.1ms 972.5ms 53.0ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: ad1215f86a3c; PR package: c921008. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 1.031s 1.084s 0.95x 736.25 MiB 745.25 MiB 1.01x 999.85 MiB/s 951.45 MiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 210.9ms 215.8ms 0.98x 89.50 MiB 92.75 MiB 1.04x 4.77 GiB/s 4.67 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 939.1ms 1.07 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 961.9ms 1.05 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 199.5ms 5.05 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 147.1ms 6.84 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 49.3ms 57.1ms 0.86x 43.00 MiB 43.25 MiB 1.01x 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 53.9ms 51.9ms 1.04x 43.00 MiB 43.00 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex daily --offline --json 0.00 MiB 55.9ms 52.6ms 1.06x 43.00 MiB 43.25 MiB 1.01x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 51.5ms 54.2ms 0.95x 43.00 MiB 43.00 MiB 1.00x 0.02 MiB/s 0.02 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 914.6ms 954.6ms 0.96x 736.00 MiB 741.50 MiB 1.01x 1.10 GiB/s 1.05 GiB/s
codex --offline --json 1.01 GiB 201.1ms 185.3ms 1.09x 93.00 MiB 90.25 MiB 0.97x 5.01 GiB/s 5.43 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.32 KiB 17.32 KiB +0.00 KiB 1.00x
installed native package binary 3324.77 KiB 3324.77 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

The crane coverage build is hermetic and has no system zoneinfo database, so
jiff could not resolve named time zones (e.g. Asia/Tokyo) and fell back to UTC.
That shifted two timezone-dependent tests by a day and failed the build, even
though they pass in the dev shell where the runner's zoneinfo is present.

Set TZDIR to the nixpkgs tzdata so jiff resolves real offsets; referencing the
store path also pulls it into the sandbox as a build input.
@pullfrog

pullfrog Bot commented Jun 11, 2026 •

Copy link
Copy Markdown
Contributor

Diagnosis

Check suite 73553293710 (commit c921008) failed during "Generate Rust coverage report" step. Two timezone-dependent tests failed because the Nix build sandbox lacks the system zoneinfo database.

Failing tests:

  • formats_dates_with_timezone — expected "2024-08-05" for timestamp in Asia/Tokyo, got "2024-08-04" (UTC fallback)
  • builds_statusline_today_filter_from_timezone — expected Some("20260522"), got Some("20260521") (same UTC fallback)

Fix

The PR author already committed the fix in 16f8a74: setting TZDIR = "${pkgs.tzdata}/share/zoneinfo" in the coverage derivation so jiff (with tz-system + tzdb-zoneinfo features) can resolve named timezones.

All 253 tests pass with TZDIR set. I verified this locally and pushed the branch to retrigger CI on the latest commit.

Task list (5/5 completed)
  • Checkout PR perf(ci): build Rust coverage as a Nix derivation #1266 branch
  • Fetch check suite logs to diagnose failure
  • Diagnose the CI failure - timezone tests need TZDIR in Nix sandbox
  • Verify fix by running tests with TZDIR
  • Commit and push changes (fix already in branch, re-check state)

Pullfrog  | View workflow run | via Pullfrog | Using Big Pickle (free via Pullfrog for OSS) | 𝕏

@github-code-quality

github-code-quality Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Code Coverage Overview

Languages: Rust

Rust / code-coverage/cargo-llvm-cov

The overall coverage in the ci/nixify-rust-cover... branch remains at 77%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main d18721f ci/nixify-rust-cover... 16f8a74 +/-
crates/ccusage/src/pricing.rs 97% 96% -1%
crates/ccusage/src/progress.rs 52% 89% +37%

Updated June 11, 2026 14:51 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 16f8a74fe08c
Base SHA: ad1215f86a3c

This compares the Rust PR release binary against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new ad1215f86a3c 626.7ms 772.0ms 48.4ms 3
PR pkg.pr.new 16f8a74 791.9ms 939.9ms 54.8ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: ad1215f86a3c; PR package: 16f8a74. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 825.1ms 988.1ms 0.84x 733.75 MiB 729.50 MiB 0.99x 1.22 GiB/s 1.02 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 175.2ms 189.0ms 0.93x 88.25 MiB 87.75 MiB 0.99x 5.75 GiB/s 5.33 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 827.7ms 1.22 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 870.1ms 1.16 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 214.4ms 4.70 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 142.9ms 7.04 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 48.5ms 5.1ms 9.51x - 2.75 MiB - 0.03 MiB/s 0.30 MiB/s
claude session --offline --json 0.00 MiB 51.0ms 5.0ms 10.12x 43.00 MiB 2.75 MiB 0.06x 0.03 MiB/s 0.31 MiB/s
codex daily --offline --json 0.00 MiB 46.8ms 4.7ms 10.05x 43.25 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.18 MiB/s
codex session --offline --json 0.00 MiB 45.3ms 4.8ms 9.50x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.18 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 825.3ms 756.9ms 1.09x 734.25 MiB 722.75 MiB 0.98x 1.22 GiB/s 1.33 GiB/s
codex --offline --json 1.01 GiB 200.1ms 197.2ms 1.02x 91.25 MiB 88.25 MiB 0.97x 5.03 GiB/s 5.11 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.32 KiB 17.32 KiB -0.00 KiB 1.00x
installed native package binary 3324.77 KiB 3324.77 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 16f8a74fe08c
Base SHA: ad1215f86a3c

This compares the PR package against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new ad1215f86a3c 880.1ms 742.5ms 55.2ms 3
PR pkg.pr.new 16f8a74 981.0ms 1.150s 52.2ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: ad1215f86a3c; PR package: 16f8a74. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 936.7ms 978.5ms 0.96x 727.25 MiB 732.25 MiB 1.01x 1.07 GiB/s 1.03 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 199.0ms 200.7ms 0.99x 90.75 MiB 90.50 MiB 1.00x 5.06 GiB/s 5.02 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 951.6ms 1.06 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 927.1ms 1.09 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 177.5ms 5.67 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 148.8ms 6.77 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 52.0ms 48.1ms 1.08x - 43.25 MiB - 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 48.0ms 48.2ms 1.00x 43.00 MiB 43.00 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex daily --offline --json 0.00 MiB 49.9ms 49.5ms 1.01x 43.25 MiB 43.00 MiB 0.99x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 45.8ms 45.2ms 1.01x 43.25 MiB 43.00 MiB 0.99x 0.02 MiB/s 0.02 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 1.016s 985.1ms 1.03x 724.50 MiB 733.50 MiB 1.01x 1015.06 MiB/s 1.02 GiB/s
codex --offline --json 1.01 GiB 185.1ms 185.1ms 1.00x 87.25 MiB 89.00 MiB 1.02x 5.44 GiB/s 5.44 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.32 KiB 17.32 KiB -0.00 KiB 1.00x
installed native package binary 3324.77 KiB 3324.77 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant