Skip to content

ci(cache): scope macOS Nix cache key by target arch - #1294

Merged
ryoppippi merged 2 commits into
mainfrom
fix/mac-x64-cache-key
Jun 12, 2026
Merged

ryoppippi merged 2 commits into
mainfrom
fix/mac-x64-cache-key

Conversation

@ryoppippi

@ryoppippi ryoppippi commented Jun 11, 2026 •

Copy link
Copy Markdown
Member

Summary

The arm64 and x64 macOS native packages both build on the same arm64 Blacksmith runner (x64 cross-compiles via the multi-arch Apple SDK), so runner.os/runner.arch are identical for both. They shared one cache-nix-action key (nix-macOS-ARM64-<hash>) and clobbered each other's restored Nix store every run — leaving the Intel build effectively uncached and cold.

What changed

  • Added a key-suffix input to setup-macos-nix-cache that is appended to the primary key, restore prefix, and purge prefix.
  • Added a cache-key-suffix input to setup-nix that forwards to the macOS cache action.
  • build-macos-nix-native-package now passes the target arch as the suffix.

Result: build-mac-arm64 → nix-macOS-ARM64-arm64-<hash>, build-mac-x64 → nix-macOS-ARM64-x64-<hash>. Independent caches, no clobber. Both keys re-warm once on first run.


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


Summary by cubic

Scope the macOS Nix cache key by target arch so arm64 and x64 builds get separate caches on the shared arm64 runner. Stops cache clobbering and keeps both builds warm.

  • Bug Fixes
    • Added key-suffix to setup-macos-nix-cache and applied it to primary, restore, and purge keys.
    • Added cache-key-suffix to setup-nix and forwarded it to setup-macos-nix-cache.
    • build-macos-nix-native-package passes the target arch as the suffix (e.g., nix-macOS-ARM64-arm64-<hash> and ...-x64-<hash>).

Written for commit c9be5a0. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Chores
    • Scoped macOS Nix build cache by adding architecture-specific cache keys and configurable key suffixes, preventing arm64/x64 cache clobbering on shared runners. Also updated cache purge/restore behaviors to target scoped entries, resulting in more reliable, isolated macOS builds and reduced cache-related failures across architectures and CI run stability. No functional changes to build outputs.

The arm64 and x64 macOS native packages both build on the same arm64
Blacksmith runner (x64 cross-compiles via the multi-arch Apple SDK), so
runner.os and runner.arch are identical for both jobs. They therefore
shared a single cache-nix-action key (`nix-macOS-ARM64-<hash>`) and
clobbered each other's restored store on every run, leaving the Intel
build effectively uncached.

Thread a `cache-key-suffix` input through setup-nix into
setup-macos-nix-cache and pass the target arch from
build-macos-nix-native-package, so build-mac-arm64 and build-mac-x64
get independent cache entries.
@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 c9be5a0 Commit Preview URL

Branch Preview URL
Jun 11 2026, 11:58 PM

@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: a6658c3a-98f6-451d-b104-503b2da06b4e

📥 Commits

Reviewing files that changed from the base of the PR and between c65b8ea and c9be5a0.

📒 Files selected for processing (1)
  • .github/actions/setup-nix/action.yaml

📝 Walkthrough

Walkthrough

Three composite GitHub Actions are updated to thread an architecture-scoped cache-key suffix: setup-nix declares cache-key-suffix, setup-macos-nix-cache accepts key-suffix and embeds it into cache keys, and the macOS build action passes inputs.arch as the suffix.

Changes

macOS Nix Cache Scoping

Layer / File(s) Summary
Cache-key-suffix input declaration
.github/actions/setup-nix/action.yaml
setup-nix action declares a new cache-key-suffix input (default '') and forwards it to the macOS cache step.
macOS Nix cache key scoping
.github/actions/setup-macos-nix-cache/action.yaml
setup-macos-nix-cache adds inputs.key-suffix and embeds it into primary-key, restore-prefixes-first-match, and purge-prefixes so cache entries are scoped by the suffix.
Architecture-scoped cache integration
.github/actions/build-macos-nix-native-package/action.yaml
build-macos-nix-native-package passes inputs.arch as the cache-key-suffix into setup-nix, ensuring arm64 and x64 builds use separate Nix caches on shared runners.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • ccusage/ccusage#1249: Earlier macOS Nix cache setup migration that overlaps in cache setup logic and keys.
  • ccusage/ccusage#1289: Related per-architecture macOS build changes that use the same inputs.arch parameter.
  • ccusage/ccusage#1254: Modifies cache-key computation for the same macOS Nix cache action.

Suggested reviewers

  • pullfrog

Poem

🐰 I hopped through YAML, trailing a suffix so small,
Two arches now live in their own little stall.
Each build keeps its cache, no more runner distress—
A neat little thread, made tidy and stressless. ✨

🚥 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 'ci(cache): scope macOS Nix cache key by target arch' clearly and specifically summarizes the main change: adding architecture-scoped cache keys for macOS Nix builds to prevent cache clobbering between arm64 and x64 builds.
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 fix/mac-x64-cache-key

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

@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.

Caution

The cache-key-suffix input on setup-nix is declared but never forwarded to setup-macos-nix-cache, making the entire change a no-op.

Reviewed changes — scope the macOS Nix cache key by target arch so arm64 and x64 builds on the shared arm64 runner get independent caches.

  • Add key-suffix input to setup-macos-nix-cache — appended to primary-key, restore-prefix, and purge-prefix
  • Add cache-key-suffix input to setup-nix — declared with a description and default, intended to forward to the macOS cache action
  • Pass arch from build-macos-nix-native-package to setup-nix via the new input

Note: 1 inline comment(s) dropped because they did not anchor to lines inside the PR diff:

  • .github/actions/setup-nix/action.yaml:20 (RIGHT) — line 20 (RIGHT) is not inside a diff hunk

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

@pullfrog

pullfrog Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Technical details for the setup-nix forwarding issue

The setup-nix/action.yaml declares cache-key-suffix as an input (lines 3-6) but the step that calls setup-macos-nix-cache at line 20 has no with: block:

    - uses: ./.github/actions/setup-macos-nix-cache
      if: runner.os == 'macOS'

Without forwarding, key-suffix on the cache action always resolves to its default: '', so the cache key is unchanged and the two arch builds still clobber each other.

Fix: Add a with: block:

    - uses: ./.github/actions/setup-macos-nix-cache
      if: runner.os == 'macOS'
      with:
        key-suffix: ${{ inputs.cache-key-suffix }}

This is the only missing piece — the rest of the threading (build-macos-nix-native-package → setup-nix → setup-macos-nix-cache) is correct.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/actions/setup-nix/action.yaml (1)

20-21: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Forward cache-key-suffix to the macOS cache action.

The cache-key-suffix input declared at lines 4-6 is never passed to setup-macos-nix-cache. Without this forwarding, the architecture-scoped cache keys won't be generated, and arm64/x64 builds will still clobber each other's Nix store cache.

🔧 Proposed fix
     - uses: ./.github/actions/setup-macos-nix-cache
       if: runner.os == 'macOS'
+      with:
+        key-suffix: ${{ inputs.cache-key-suffix }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/actions/setup-nix/action.yaml around lines 20 - 21, The macOS step
that uses ./.github/actions/setup-macos-nix-cache is not forwarding the declared
input cache-key-suffix, so add a with block to that step to pass
cache-key-suffix: ${{ inputs.cache-key-suffix }} (i.e., update the step that
references ./.github/actions/setup-macos-nix-cache to include a with:
cache-key-suffix: ${{ inputs.cache-key-suffix }} entry) so architecture-scoped
cache keys are generated correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.github/actions/setup-nix/action.yaml:
- Around line 20-21: The macOS step that uses
./.github/actions/setup-macos-nix-cache is not forwarding the declared input
cache-key-suffix, so add a with block to that step to pass cache-key-suffix: ${{
inputs.cache-key-suffix }} (i.e., update the step that references
./.github/actions/setup-macos-nix-cache to include a with: cache-key-suffix: ${{
inputs.cache-key-suffix }} entry) so architecture-scoped cache keys are
generated correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: db58a337-5483-4c33-9f98-cec749fc4eae

📥 Commits

Reviewing files that changed from the base of the PR and between 7bcafc9 and c65b8ea.

📒 Files selected for processing (3)
  • .github/actions/build-macos-nix-native-package/action.yaml
  • .github/actions/setup-macos-nix-cache/action.yaml
  • .github/actions/setup-nix/action.yaml

@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@1294

@ccusage/ccusage-darwin-arm64

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

@ccusage/ccusage-darwin-x64

npx https://pkg.pr.new/@ccusage/ccusage-darwin-x64@1294

@ccusage/ccusage-linux-arm64

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

@ccusage/ccusage-linux-x64

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

@ccusage/ccusage-win32-x64

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

commit: c9be5a0

@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.

2 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/actions/setup-nix/action.yaml">

<violation number="1" location=".github/actions/setup-nix/action.yaml:4">
P2: New `cache-key-suffix` input is defined but never forwarded to the macOS cache action, so it has no effect.</violation>
</file>

<file name=".github/actions/setup-macos-nix-cache/action.yaml">

<violation number="1" location=".github/actions/setup-macos-nix-cache/action.yaml:16">
P2: Empty `key-suffix` still adds a separator, unintentionally changing the default cache namespace.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

name: Setup Nix
description: Install Nix with platform-specific cache setup
inputs:
cache-key-suffix:

@cubic-dev-ai cubic-dev-ai Bot Jun 11, 2026 •

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.

P2: New cache-key-suffix input is defined but never forwarded to the macOS cache action, so it has no effect.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/actions/setup-nix/action.yaml, line 4:

<comment>New `cache-key-suffix` input is defined but never forwarded to the macOS cache action, so it has no effect.</comment>

<file context>
@@ -1,5 +1,9 @@
 name: Setup Nix
 description: Install Nix with platform-specific cache setup
+inputs:
+  cache-key-suffix:
+    description: Extra suffix to scope the macOS Nix cache key (e.g. cross target arch)
+    default: ''
</file context>
Fix with cubic

with:
primary-key: nix-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('flake.lock', 'flake.nix', 'default.nix', 'package.nix', 'package.json', 'nix/**/*.nix', 'rust-toolchain.toml', 'rust/Cargo.lock', 'rust/**/Cargo.toml') }}
restore-prefixes-first-match: nix-${{ runner.os }}-${{ runner.arch }}-
primary-key: nix-${{ runner.os }}-${{ runner.arch }}-${{ inputs.key-suffix }}-${{ hashFiles('flake.lock', 'flake.nix', 'default.nix', 'package.nix', 'package.json', 'nix/**/*.nix', 'rust-toolchain.toml', 'rust/Cargo.lock', 'rust/**/Cargo.toml') }}

@cubic-dev-ai cubic-dev-ai Bot Jun 11, 2026 •

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.

P2: Empty key-suffix still adds a separator, unintentionally changing the default cache namespace.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/actions/setup-macos-nix-cache/action.yaml, line 16:

<comment>Empty `key-suffix` still adds a separator, unintentionally changing the default cache namespace.</comment>

<file context>
@@ -1,15 +1,22 @@
       with:
-        primary-key: nix-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('flake.lock', 'flake.nix', 'default.nix', 'package.nix', 'package.json', 'nix/**/*.nix', 'rust-toolchain.toml', 'rust/Cargo.lock', 'rust/**/Cargo.toml') }}
-        restore-prefixes-first-match: nix-${{ runner.os }}-${{ runner.arch }}-
+        primary-key: nix-${{ runner.os }}-${{ runner.arch }}-${{ inputs.key-suffix }}-${{ hashFiles('flake.lock', 'flake.nix', 'default.nix', 'package.nix', 'package.json', 'nix/**/*.nix', 'rust-toolchain.toml', 'rust/Cargo.lock', 'rust/**/Cargo.toml') }}
+        restore-prefixes-first-match: nix-${{ runner.os }}-${{ runner.arch }}-${{ inputs.key-suffix }}-
         gc-max-store-size-macos: 3500000000
</file context>
Fix with cubic

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: c65b8ea918db
Base SHA: 7bcafc9a7da2

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 7bcafc9a7da2 2.103s 1.856s 61.9ms 3
PR pkg.pr.new c65b8ea 2.404s 2.043s 62.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: 7bcafc9a7da2; PR package: c65b8ea. 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 895.6ms 916.1ms 0.98x 732.50 MiB 736.75 MiB 1.01x 1.12 GiB/s 1.10 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 199.4ms 199.3ms 1.00x 90.25 MiB 91.00 MiB 1.01x 5.05 GiB/s 5.05 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 907.6ms 1.11 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 872.1ms 1.15 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 174.1ms 5.78 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 133.7ms 7.53 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 46.5ms 5.7ms 8.11x 43.25 MiB 2.75 MiB 0.06x 0.03 MiB/s 0.27 MiB/s
claude session --offline --json 0.00 MiB 44.0ms 5.8ms 7.55x 43.00 MiB 2.75 MiB 0.06x 0.04 MiB/s 0.27 MiB/s
codex daily --offline --json 0.00 MiB 42.1ms 5.4ms 7.75x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.16 MiB/s
codex session --offline --json 0.00 MiB 43.7ms 5.5ms 7.99x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.16 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 855.0ms 833.6ms 1.03x 734.00 MiB 744.75 MiB 1.01x 1.18 GiB/s 1.21 GiB/s
codex --offline --json 1.01 GiB 170.2ms 133.0ms 1.28x 89.75 MiB 90.00 MiB 1.00x 5.91 GiB/s 7.57 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.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: c65b8ea918db
Base SHA: 7bcafc9a7da2

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 7bcafc9a7da2 2.787s 1.982s 61.6ms 3
PR pkg.pr.new c65b8ea 2.370s 2.411s 62.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: 7bcafc9a7da2; PR package: c65b8ea. 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.016s 956.2ms 1.06x 730.25 MiB 735.00 MiB 1.01x 1014.51 MiB/s 1.05 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 212.3ms 213.6ms 0.99x 92.00 MiB 92.00 MiB 1.00x 4.74 GiB/s 4.71 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.015s 1016.06 MiB/s 1
claude --offline --json Installed native binary 1.01 GiB 900.3ms 1.12 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 183.3ms 5.49 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 140.0ms 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 52.5ms 45.3ms 1.16x 43.00 MiB 43.25 MiB 1.01x 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 50.3ms 40.6ms 1.24x 43.00 MiB 43.00 MiB 1.00x 0.03 MiB/s 0.04 MiB/s
codex daily --offline --json 0.00 MiB 39.6ms 39.9ms 0.99x 43.25 MiB 43.00 MiB 0.99x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 38.9ms 37.4ms 1.04x 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 918.4ms 923.0ms 1.00x 725.00 MiB 734.00 MiB 1.01x 1.10 GiB/s 1.09 GiB/s
codex --offline --json 1.01 GiB 172.3ms 168.1ms 1.02x 91.75 MiB 89.75 MiB 0.98x 5.84 GiB/s 5.99 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.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: c9be5a0adc61
Base SHA: 7bcafc9a7da2

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 7bcafc9a7da2 996.0ms 800.5ms 55.0ms 3
PR pkg.pr.new c9be5a0 864.4ms 833.3ms 56.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: 7bcafc9a7da2; PR package: c9be5a0. 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 818.3ms 754.3ms 1.08x 736.50 MiB 740.50 MiB 1.01x 1.23 GiB/s 1.33 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 171.9ms 174.2ms 0.99x 91.00 MiB 89.00 MiB 0.98x 5.85 GiB/s 5.78 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 797.0ms 1.26 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 737.2ms 1.37 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 154.1ms 6.53 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 118.8ms 8.47 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 40.7ms 4.5ms 9.09x 44.00 MiB 2.75 MiB 0.06x 0.04 MiB/s 0.34 MiB/s
claude session --offline --json 0.00 MiB 37.9ms 4.5ms 8.48x 44.25 MiB 2.75 MiB 0.06x 0.04 MiB/s 0.35 MiB/s
codex daily --offline --json 0.00 MiB 36.8ms 4.1ms 8.92x 44.25 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.21 MiB/s
codex session --offline --json 0.00 MiB 37.2ms 4.2ms 8.86x 44.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 762.5ms 714.2ms 1.07x 731.75 MiB 744.25 MiB 1.02x 1.32 GiB/s 1.41 GiB/s
codex --offline --json 1.01 GiB 151.4ms 120.7ms 1.25x 93.00 MiB 93.75 MiB 1.01x 6.65 GiB/s 8.34 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.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: c9be5a0adc61
Base SHA: 7bcafc9a7da2

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 7bcafc9a7da2 862.1ms 691.5ms 62.9ms 3
PR pkg.pr.new c9be5a0 769.6ms 809.1ms 63.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: 7bcafc9a7da2; PR package: c9be5a0. 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 884.9ms 984.4ms 0.90x 723.75 MiB 725.50 MiB 1.00x 1.14 GiB/s 1.02 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 198.9ms 192.2ms 1.04x 93.75 MiB 90.50 MiB 0.97x 5.06 GiB/s 5.24 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 846.6ms 1.19 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 972.9ms 1.03 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 175.2ms 5.75 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 133.8ms 7.52 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 43.3ms 40.6ms 1.07x 43.00 MiB 42.75 MiB 0.99x 0.04 MiB/s 0.04 MiB/s
claude session --offline --json 0.00 MiB 45.1ms 39.3ms 1.15x 43.00 MiB 43.00 MiB 1.00x 0.03 MiB/s 0.04 MiB/s
codex daily --offline --json 0.00 MiB 39.3ms 43.6ms 0.90x 43.00 MiB 43.00 MiB 1.00x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 40.1ms 39.8ms 1.01x 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 806.6ms 859.8ms 0.94x 703.50 MiB 727.50 MiB 1.03x 1.25 GiB/s 1.17 GiB/s
codex --offline --json 1.01 GiB 180.8ms 182.6ms 0.99x 90.00 MiB 91.50 MiB 1.02x 5.57 GiB/s 5.51 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.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.

@ryoppippi
ryoppippi merged commit c794d80 into main Jun 12, 2026
27 checks passed
@ryoppippi
ryoppippi deleted the fix/mac-x64-cache-key branch June 12, 2026 00:05
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