Skip to content

perf(ci): run CI once per change instead of twice - #1268

Merged
ryoppippi merged 2 commits into
mainfrom
ci/push-main-only
Jun 11, 2026
Merged

perf(ci): run CI once per change instead of twice#1268
ryoppippi merged 2 commits into
mainfrom
ci/push-main-only

Conversation

@ryoppippi

@ryoppippi ryoppippi commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

Every commit on a PR branch triggered the full CI workflow twice — once for
the push event and once for pull_request — duplicating the check, test,
and the entire native-build matrix.

What changed

  • Restrict push to the main branch. Branch commits are now validated once
    via the pull_request event; main keeps its post-merge run.
  • Remove the dead Run test suite step (it only fired on pushes to non-default
    branches, which no longer happen).
  • Drop the now-always-true event guards on the Vitest and coverage steps.

Why / safety

Rust tests stay fully covered: the coverage step runs cargo llvm-cov over the
whole workspace on both remaining triggers, so the removed just test path is
redundant. The upload step keeps its fork guard.

Tradeoff: pushing a branch without an open PR no longer runs CI. Opening
the PR runs it. This is the intended cost saving — it roughly halves CI minutes
spent per PR.

Verify

This very PR should show a single CI run (the pull_request run); the push
run for the branch is suppressed by the new on.push.branches filter on the
branch's own workflow file.


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


Summary by cubic

Run CI once per change by limiting push to main and relying on pull_request for branches; branch pushes without an open PR no longer run CI. Speed up the test job by installing only pnpm, bun, and just instead of realizing the full Nix dev shell.

  • Refactors
    • Removed the unused "Run test suite" step (it only ran on non-default branch pushes).
    • Dropped always-true event guards for Vitest and Rust coverage; kept and simplified the fork guard on actions/upload-code-coverage.
    • Replaced Nix dev shell warmup with direct JS tooling install and just test-vitest; coverage stays a nix build derivation.

Written for commit 6d4ea65. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Chores
    • CI workflow now only triggers on the main branch.
    • Simplified test execution and coverage reporting flow.
    • Streamlined logic for uploading coverage artifacts so reports are uploaded for non-PRs and for PRs originating from the main repository.

`on: { push, pull_request }` with no branch filter meant every push to a PR
branch triggered the full workflow twice — once for `push` and once for
`pull_request` — duplicating the check, test, and native-build matrix on every
commit.

Restrict `push` to `main` so branch commits are validated once via the
`pull_request` event, while main keeps its post-merge run. Rust tests stay
covered: the `Run test suite` step only fired on pushes to non-default
branches (now gone), and the coverage step already runs `cargo llvm-cov` over
the workspace on both remaining triggers. Drop that dead step and the
now-always-true event guards on the Vitest and coverage steps.
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b9d53bf5-6fdf-46ad-99c7-d2550011fc3a

📥 Commits

Reviewing files that changed from the base of the PR and between 7a38566 and 6d4ea65.

📒 Files selected for processing (1)
  • .github/workflows/ci.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/ci.yaml

📝 Walkthrough

Walkthrough

Push trigger is restricted to the main branch. The test job now installs JS tooling, runs just test-vitest, builds Rust coverage via .#ccusage-coverage and copies coverage/cobertura.xml, and the coverage upload is gated by a simplified non-PR or PR-from-main-repo condition.

Changes

CI workflow branch and test job updates

Layer / File(s) Summary
Push trigger branch restriction
.github/workflows/ci.yaml
Push trigger now explicitly limits execution to the main branch.
Test job and coverage steps
.github/workflows/ci.yaml
Test job installs JS tooling and deps, runs just test-vitest, generates Rust coverage via .#ccusage-coverage and copies coverage/cobertura.xml, and coverage artifact upload is gated by a simplified non-PR or PR-from-main-repo condition; prior branch-based conditional logic was removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • ccusage/ccusage#1266: Adds/relates to the .#ccusage-coverage Nix derivation used here for Rust coverage generation.
  • ccusage/ccusage#1258: Also updates the test job and CI setup; overlapping changes to test/coverage steps.

Suggested reviewers

  • pullfrog

Poem

🐰 A workflow trims its branches, steady and plain,
Main calls the shots, the tests run like rain,
Vitest hops forward, coverage finds its way,
Small steps in CI to brighten the day.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main objective: reducing duplicate CI runs by limiting the push trigger to the main branch, causing CI to run once per change instead of twice.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/push-main-only

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 6d4ea65 Commit Preview URL

Branch Preview URL
Jun 11 2026, 03:21 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 — CI optimization to halve runs per change by restricting push to main and relying on pull_request for branch validation.

  • Restrict push to main — branch pushes without a PR no longer trigger CI; pull_request covers pre-merge validation. Roughly halves CI minutes per PR.
  • Remove dead "Run test suite" step — it only fired on non-default branch pushes, which no longer happen.
  • Drop always-true event guards — Vitest, coverage, and upload steps had disjuncts (github.event_name == 'pull_request' || github.ref == ...) that are universally true under the new trigger scope. Removed with no behavioral change.
  • Simplify fork-guard on upload — algebraically equivalent to the original; verified by truth table for push/main, same-repo PR, and fork PR.

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

@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 1 file

Re-trigger cubic

@pkg-pr-new

pkg-pr-new Bot commented Jun 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

@ccusage/ccusage-darwin-arm64

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

@ccusage/ccusage-linux-arm64

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

@ccusage/ccusage-linux-x64

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

@ccusage/ccusage-win32-x64

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

ccusage

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

commit: 7a38566

@github-code-quality

Copy link
Copy Markdown

Code Coverage Overview

Languages: Rust

Rust / code-coverage/cargo-llvm-cov

The overall coverage in the ci/push-main-only branch remains at 77%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main 7195767 ci/push-main-only 7a38566 +/-
crates/ccusage/src/progress.rs 89% 88% -1%

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: 7a385661f167
Base SHA: 71957676b778

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 71957676b778 1.032s 837.2ms 53.8ms 3
PR pkg.pr.new 7a38566 940.4ms 1.052s 55.1ms 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: 71957676b778; PR package: 7a38566. 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 953.9ms 960.1ms 0.99x 739.25 MiB 735.50 MiB 0.99x 1.06 GiB/s 1.05 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 193.2ms 201.0ms 0.96x 91.00 MiB 94.75 MiB 1.04x 5.21 GiB/s 5.01 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 973.4ms 1.03 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 919.3ms 1.10 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 179.3ms 5.61 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 140.1ms 7.19 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 46.0ms 46.6ms 0.99x 43.00 MiB 43.00 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 44.7ms 44.9ms 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 45.3ms 46.9ms 0.97x 43.00 MiB 43.00 MiB 1.00x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 48.1ms 48.8ms 0.99x 43.00 MiB 43.25 MiB 1.01x 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 896.1ms 1.027s 0.87x 735.25 MiB 726.75 MiB 0.99x 1.12 GiB/s 1004.33 MiB/s
codex --offline --json 1.01 GiB 175.1ms 182.4ms 0.96x 92.00 MiB 88.50 MiB 0.96x 5.75 GiB/s 5.52 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.33 KiB 17.32 KiB -0.00 KiB 1.00x
installed native package binary 3324.84 KiB 3324.84 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: 7a385661f167
Base SHA: 71957676b778

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 71957676b778 981.7ms 782.3ms 50.4ms 3
PR pkg.pr.new 7a38566 872.9ms 1.001s 51.6ms 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: 71957676b778; PR package: 7a38566. 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 945.9ms 887.3ms 1.07x 729.00 MiB 731.25 MiB 1.00x 1.06 GiB/s 1.13 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 194.0ms 205.9ms 0.94x 93.75 MiB 90.75 MiB 0.97x 5.19 GiB/s 4.89 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 964.0ms 1.04 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 952.5ms 1.06 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 175.5ms 5.74 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 137.2ms 7.34 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 45.4ms 6.3ms 7.19x 43.25 MiB 3.00 MiB 0.07x 0.03 MiB/s 0.24 MiB/s
claude session --offline --json 0.00 MiB 48.4ms 5.8ms 8.42x 43.00 MiB 2.75 MiB 0.06x 0.03 MiB/s 0.27 MiB/s
codex daily --offline --json 0.00 MiB 41.9ms 6.0ms 7.04x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.14 MiB/s
codex session --offline --json 0.00 MiB 43.9ms 6.1ms 7.15x 43.25 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.14 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 868.6ms 886.7ms 0.98x 738.00 MiB 701.25 MiB 0.95x 1.16 GiB/s 1.14 GiB/s
codex --offline --json 1.01 GiB 186.2ms 137.8ms 1.35x 92.25 MiB 87.75 MiB 0.95x 5.41 GiB/s 7.30 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.33 KiB 17.32 KiB -0.00 KiB 1.00x
installed native package binary 3324.84 KiB 3324.84 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 test job spent ~73s on "Warm Nix dev shell" realizing the complete
development shell — every linter, formatter, renovate, and the pre-commit hook
closure — even though pnpm install itself was only ~7s. Now that coverage is a
`nix build` derivation, Vitest is the sole step that needs a JS toolchain.

Replace `nix develop` with `nix profile install pnpm_11 bun just`, mirroring the
perf-comment and pkg-pr-new jobs, then run `just test-vitest` directly. This
skips the heavy shell closure while keeping the exact tools Vitest needs.

@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 — incremental review of commit 6d4ea65 which replaces the full Nix dev shell warmup in the CI test job with targeted JS tooling installation, following the same pattern already established in other CI jobs in this repo.

  • Drop the full dev shell from the test job — replaces the nix develop --command true warmup with nix profile install --inputs-from . nixpkgs#pnpm_11 nixpkgs#bun nixpkgs#just followed by pnpm install --frozen-lockfile. This skips realizing the full dev shell closure, which included linters, formatters, and pre-commit hooks that aren't needed for running vitest. The vitest step now runs just test-vitest directly since the toolchain is on PATH.

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

@ryoppippi
ryoppippi merged commit d6d34c4 into main Jun 11, 2026
15 checks passed
@ryoppippi
ryoppippi deleted the ci/push-main-only branch June 11, 2026 15:17
@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 6d4ea6568421
Base SHA: 71957676b778

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 71957676b778 648.2ms 738.6ms 44.7ms 3
PR pkg.pr.new 6d4ea65 787.9ms 1.205s 45.5ms 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: 71957676b778; PR package: 6d4ea65. 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 865.5ms 849.8ms 1.02x 735.50 MiB 733.75 MiB 1.00x 1.16 GiB/s 1.18 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 166.9ms 164.6ms 1.01x 87.75 MiB 98.75 MiB 1.13x 6.03 GiB/s 6.12 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 831.4ms 1.21 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 699.8ms 1.44 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 161.4ms 6.24 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 122.1ms 8.24 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 52.5ms 4.8ms 11.05x 43.25 MiB 3.00 MiB 0.07x 0.03 MiB/s 0.33 MiB/s
claude session --offline --json 0.00 MiB 51.7ms 4.7ms 11.11x 43.25 MiB 2.75 MiB 0.06x 0.03 MiB/s 0.33 MiB/s
codex daily --offline --json 0.00 MiB 40.8ms 4.3ms 9.47x 43.25 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.20 MiB/s
codex session --offline --json 0.00 MiB 40.3ms 4.2ms 9.62x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.20 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 926.0ms 880.8ms 1.05x 752.75 MiB 735.25 MiB 0.98x 1.09 GiB/s 1.14 GiB/s
codex --offline --json 1.01 GiB 162.7ms 125.9ms 1.29x 91.50 MiB 91.50 MiB 1.00x 6.19 GiB/s 7.99 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.33 KiB 17.32 KiB -0.00 KiB 1.00x
installed native package binary 3324.84 KiB 3324.84 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: 6d4ea6568421
Base SHA: 71957676b778

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 71957676b778 746.9ms 937.1ms 57.6ms 3
PR pkg.pr.new 6d4ea65 1.266s 952.3ms 56.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: 71957676b778; PR package: 6d4ea65. 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.011s 1.079s 0.94x 731.00 MiB 733.75 MiB 1.00x 1019.95 MiB/s 955.55 MiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 219.1ms 197.7ms 1.11x 90.25 MiB 91.25 MiB 1.01x 4.60 GiB/s 5.09 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 1.042s 989.28 MiB/s 1
claude --offline --json Installed native binary 1.01 GiB 1.081s 954.02 MiB/s 1
codex --offline --json Package wrapper 1.01 GiB 195.1ms 5.16 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 142.4ms 7.07 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 47.0ms 47.5ms 0.99x 43.00 MiB 43.00 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 49.9ms 48.0ms 1.04x 43.00 MiB 43.25 MiB 1.01x 0.03 MiB/s 0.03 MiB/s
codex daily --offline --json 0.00 MiB 48.0ms 49.0ms 0.98x 43.00 MiB 42.75 MiB 0.99x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 48.5ms 49.5ms 0.98x 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 941.0ms 1.006s 0.94x 733.50 MiB 732.50 MiB 1.00x 1.07 GiB/s 1.00 GiB/s
codex --offline --json 1.01 GiB 178.0ms 188.5ms 0.94x 92.50 MiB 89.50 MiB 0.97x 5.66 GiB/s 5.34 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.33 KiB 17.32 KiB -0.00 KiB 1.00x
installed native package binary 3324.84 KiB 3324.84 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