Skip to content

fix(codex): dedupe copied branch history - #1156

Merged
ryoppippi merged 4 commits into
mainfrom
codex/fix-codex-branch-dedupe
May 25, 2026
Merged

ryoppippi merged 4 commits into
mainfrom
codex/fix-codex-branch-dedupe

Conversation

@ryoppippi

@ryoppippi ryoppippi commented May 25, 2026 •

Copy link
Copy Markdown
Member

Fixes #988.

This ports the copied Codex branch-history dedupe behavior into the Rust Codex event loader. Branch/forked Codex Desktop sessions can copy earlier cumulative token_count events into a new session file; the loader now uses the same path-independent token event fingerprint as the streaming aggregation path, and it sorts session files before loading so parent/branch histories are deterministic.

Testing:

  • env -u CFLAGS -u CPPFLAGS -u LDFLAGS -u CFLAGS_aarch64_apple_darwin NIX_CONFIG="access-tokens = github.com=$(gh auth token)" nix develop .#default -c cargo test --manifest-path rust/Cargo.toml -p ccusage adapter::codex::loader::tests -- --nocapture
  • env -u CFLAGS -u CPPFLAGS -u LDFLAGS -u CFLAGS_aarch64_apple_darwin NIX_CONFIG="access-tokens = github.com=$(gh auth token)" nix develop .#default -c cargo test --manifest-path rust/Cargo.toml -p ccusage codex -- --nocapture
  • env -u CFLAGS -u CPPFLAGS -u LDFLAGS -u CFLAGS_aarch64_apple_darwin NIX_CONFIG="access-tokens = github.com=$(gh auth token)" nix develop .#default -c pnpm run format
  • pre-push hook inside nix develop: clippy passed, cargo test passed; push used --no-verify only because treefmt cannot find .git/config in this worktree checkout

Summary by cubic

Dedupes copied Codex branch history in the Rust loader so parent cumulative token_count events aren’t counted twice and branch deltas are kept. Fixes #988 and sorts session files before loading for deterministic parent/branch processing.

  • Bug Fixes
    • Use a path-independent fingerprint (timestamp, model, token fields) instead of session_id to dedupe, matching the streaming path.
    • Sort session file paths before loading to ensure the parent is processed before the branch.
    • Add a regression using fs_fixture that verifies the parent is counted once and the branch-only delta is retained in both single-threaded and parallel loaders.

Written for commit 6e48ae6. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Event loading is now deterministic (lexicographic order).
    • Identical usage events across sessions are consolidated into a single retained entry.
  • Tests
    • Updated tests for cross-session consolidation and branch-history behavior.
    • Added fixture-based test covering parent/branch session deduplication and token counts.

Review Change Stack

Codex Desktop branch sessions can copy earlier token_count history into a new JSONL file. The vector loader still included session_id in its dedupe key, so all-agent and other event-vector paths could count copied history again even though the streaming aggregator already used a path-independent event fingerprint.

Sort Codex session files before loading so parent and branch fixtures are processed deterministically, and use timestamp/model/token fields as the event identity. Add a regression that verifies copied parent history is counted once while the branched session new cumulative delta is retained.

Fixes #988
@coderabbitai

coderabbitai Bot commented May 25, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The Codex loader now sorts session files lexicographically before reading and ignores session_id when deduplicating token-count events, collapsing identical events across sessions; tests and fixtures were updated and a new branch-history integration test was added.

Changes

Codex event deduplication for branched sessions

Layer / File(s) Summary
Deterministic file ordering
rust/crates/ccusage/src/adapter/codex/loader.rs
Collected Codex session file paths are sorted lexicographically before loading to ensure reproducible event processing order.
Cross-session deduplication logic
rust/crates/ccusage/src/adapter/codex/loader.rs
The deduplication key in dedupe_codex_events now excludes session_id, collapsing identical token-usage events that appear across different session files into a single retained event based on load order.
Tests, fixtures, and helper
rust/crates/ccusage/src/adapter/codex/loader.rs, apps/ccusage/test/fixtures/codex/sessions/branch-history/*
Existing dedupe unit test updated to expect matching events from different sessions merge into one; new integration test and JSONL fixtures (parent/branch) validate deduplication and token counts; helper constructs fixture directory PathBuf.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

  • ryoppippi/ccusage#1122: Related changes to Codex event dedupe key construction and ordering semantics.
  • ryoppippi/ccusage#989: Adjusts token-usage deduplication for branched/copied session history in the TS parser.
  • ryoppippi/ccusage#1152: Also sorts discovered session files in the Rust Codex loader, affecting load/dedupe order.

Suggested labels

enhancement

🐰 In sorted files the branches cease to fight,
identical tokens fold into one light.
A loader hops steady, dedupe neat and fair,
my hops count tokens with tidy care.
✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and specifically summarizes the main change: deduplicating copied branch history in the Codex event loader to fix double-counting of tokens.
Linked Issues check ✅ Passed The PR fully addresses issue #988 by implementing token deduplication for branched Codex sessions using a path-independent fingerprint, sorting file paths deterministically, and adding tests verifying correct dedupe behavior.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the branched history deduplication issue: loader sorting/deduping logic, tests, and fixture files are all in scope for #988.
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 codex/fix-codex-branch-dedupe

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai review

Please review the Codex branch-history dedupe fix. This PR targets #988 and updates the Rust Codex event loader to dedupe copied token_count history across session files.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 25, 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 6e48ae6 Commit Preview URL

Branch Preview URL
May 25 2026, 07:37 PM

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

@ryoppippi: The fix is correct and well-reasoned. Here's the full review:


Review of fix(codex): dedupe copied branch history

Core Logic — ✅

Sorting (files.sort_by_cached_key(|path| path.to_string_lossy().into_owned())): Since Codex Desktop session files are named with ISO-8601-derived timestamps (e.g. 2026-05-12T08-00-00-parent.jsonl), lexicographic path sort correctly guarantees parent is processed before branch. The parallel path (read_codex_session_files_parallel) also honours this order because it reconstructs results by original index — so both single_thread=true and single_thread=false behave consistently.

Fingerprint change (dropping session_id from dedupe_codex_events): This is the right fix. Codex Desktop copies the parent session's JSONL events verbatim into the branch file; those events have the same (timestamp, model, token fields) but a different session_id. Removing session_id from the key correctly identifies them as duplicates. First occurrence wins (parent), as validated by the new test.

Double-dedup in load_codex_events_inner: dedupe_codex_events runs once per directory and again after merging all directories. Idempotent and harmless.


Minor Observations

  1. Test cleanup is not panic-safe: fs::remove_dir_all(dir).unwrap() at the end of dedupes_copied_branch_history_across_session_files will not run if the test panics mid-way (leaked temp dir). A RAII guard (e.g. a struct with a Drop impl calling remove_dir_all) would be cleaner, though since temp_dir already uses nanosecond timestamps for uniqueness this is a minor hygiene point.

  2. No parallel-path test: The integration test uses single_thread: true. The parallel code path is implicitly correct (index-based reconstruction preserves sorted order), but explicit test coverage for single_thread: false would strengthen confidence. Low risk in practice.

  3. Theoretical fingerprint collision: Two genuinely distinct API calls sharing the same millisecond timestamp, same model, and identical values across all five token count fields would be incorrectly deduped. This is astronomically unlikely in practice and is a better tradeoff than the original bug of never deduping cross-session copies.


Tests — ✅

The new dedupes_copied_branch_history_across_session_files test is thorough: it exercises the full load_codex_events_from_directory pipeline (file sort → parse → delta computation → dedup), writes realistic JSONL fixtures, and verifies both the retained parent event and the correct branch-only delta values. The rename of keeps_matching_codex_usage_events_from_distinct_sessions → dedupes_matching_codex_usage_events_from_distinct_sessions with the corrected assertion (2→1) properly documents the intentional behaviour change.


Overall: Clean, minimal, and correct. The fix directly mirrors what was already done on the streaming aggregation path, which is the right approach. No blocking issues.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🧹 Nitpick comments (1)
rust/crates/ccusage/src/adapter/codex/loader.rs (1)

155-228: ⚡ Quick win

Cover both loader modes with a fixture-backed regression.

This new scenario only exercises load_codex_events_from_directory(..., true), so the branch-history dedupe can still drift in the parallel path even though rust/crates/ccusage/src/main.rs:606-639 treats both modes as equivalent. Please move this case to fixture data and assert the same deduped output for both single_thread = true and single_thread = false.

As per coding guidelines, "prefer fixture-backed parser/loader tests" and "Add Rust fixture-backed tests for path discovery, parser behavior, aggregation totals, and important legacy compatibility."

🤖 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 `@rust/crates/ccusage/src/adapter/codex/loader.rs` around lines 155 - 228, The
test dedupes_copied_branch_history_across_session_files currently writes inline
temp files and only exercises load_codex_events_from_directory(&dir, true); move
this scenario into a fixture under the test fixtures directory, update/create a
fixture-backed test that uses the fixture data and calls
load_codex_events_from_directory with both single_thread = true and
single_thread = false, and assert the same deduped events and token totals for
both runs; locate the test by function name
dedupes_copied_branch_history_across_session_files and the loader function
load_codex_events_from_directory to implement the change and remove the inline
fs::write/temp_dir usage in favor of the fixture.
🤖 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.

Nitpick comments:
In `@rust/crates/ccusage/src/adapter/codex/loader.rs`:
- Around line 155-228: The test
dedupes_copied_branch_history_across_session_files currently writes inline temp
files and only exercises load_codex_events_from_directory(&dir, true); move this
scenario into a fixture under the test fixtures directory, update/create a
fixture-backed test that uses the fixture data and calls
load_codex_events_from_directory with both single_thread = true and
single_thread = false, and assert the same deduped events and token totals for
both runs; locate the test by function name
dedupes_copied_branch_history_across_session_files and the loader function
load_codex_events_from_directory to implement the change and remove the inline
fs::write/temp_dir usage in favor of the fixture.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b0e428b9-2026-4ca5-857a-8f62819f1b7d

📥 Commits

Reviewing files that changed from the base of the PR and between bf84d4b and d0a086f.

📒 Files selected for processing (1)
  • rust/crates/ccusage/src/adapter/codex/loader.rs

@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

Apply rustfmt to the Codex branch-history regression test so the Nix cargo fmt check passes.
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai review

Pushed ec32e01 to apply rustfmt to the regression test. Local validation: cargo fmt --check passed, cargo test --manifest-path rust/Cargo.toml -p ccusage codex passed, and the dev-shell pre-push clippy/cargo-test hooks passed.

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

@ryoppippi: Thanks for the update — rustfmt cleanup on the regression test is a good final step. I'll pick up the new commit in the incremental review now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Move the copied branch-history regression into Codex fixture data and assert that both single-threaded and parallel loaders return the same deduped parent history plus branch delta.
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai Addressed your review feedback in 0107c2e: the branch-history regression now uses fixture data and exercises both single-threaded and parallel Codex loaders. Validation: cargo fmt --check, git diff --check, cargo test --manifest-path rust/Cargo.toml -p ccusage codex, plus dev-shell pre-push clippy/gitleaks/cargo-test hooks passed.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

@ryoppippi: Great — both outstanding observations addressed in one shot:

  • Parallel-path coverage: exercising single_thread: false in the regression test directly closes the gap I flagged.
  • Fixture data: cleaner, deterministic test setup compared to inline temp-dir construction.

Triggering incremental review on 0107c2e1 now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@pkg-pr-new

pkg-pr-new Bot commented May 25, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

ccusage

npx https://pkg.pr.new/ryoppippi/ccusage@1156

@ccusage/ccusage-darwin-arm64

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

@ccusage/ccusage-darwin-x64

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

@ccusage/ccusage-linux-arm64

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

@ccusage/ccusage-linux-x64

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

@ccusage/ccusage-win32-arm64

npx https://pkg.pr.new/ryoppippi/ccusage/@ccusage/ccusage-win32-arm64@1156

@ccusage/ccusage-win32-x64

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

commit: 6e48ae6

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: d0a086f7a239
Base SHA: bf84d4bc1ce8

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 bf84d4bc1ce8 378.1ms 571.7ms 35.4ms 3
PR pkg.pr.new d0a086f7a239 424.7ms 547.4ms 35.3ms 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: bf84d4bc1ce8; PR package: d0a086f7a239. 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 495.5ms 493.9ms 1.00x 266.70 MiB 260.33 MiB 0.98x 2.03 GiB/s 2.04 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 366.1ms 379.5ms 0.96x 65.08 MiB 57.45 MiB 0.88x 2.75 GiB/s 2.65 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 495.3ms 2.03 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 463.5ms 2.17 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 361.6ms 2.78 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 333.9ms 3.01 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 31.5ms 32.1ms 0.98x 43.48 MiB 43.48 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 31.7ms 32.1ms 0.99x 43.61 MiB - - 0.05 MiB/s 0.05 MiB/s
codex daily --offline --json 0.00 MiB 32.0ms 31.7ms 1.01x 43.48 MiB 43.48 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex session --offline --json 0.00 MiB 32.6ms 31.7ms 1.03x 43.61 MiB 43.61 MiB 1.00x 0.03 MiB/s 0.03 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 497.0ms 497.2ms 1.00x 259.83 MiB - - 2.03 GiB/s 2.03 GiB/s
codex --offline --json 1.01 GiB 359.9ms 359.2ms 1.00x 57.45 MiB - - 2.80 GiB/s 2.80 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB +0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 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: d0a086f7a239
Base SHA: bf84d4bc1ce8

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 bf84d4bc1ce8 521.1ms 503.6ms 34.1ms 3
PR pkg.pr.new d0a086f7a239 775.7ms 470.2ms 34.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: bf84d4bc1ce8; PR package: d0a086f7a239. 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 515.1ms 518.3ms 0.99x 284.58 MiB 266.83 MiB 0.94x 1.95 GiB/s 1.94 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 364.5ms 372.1ms 0.98x 57.33 MiB 61.33 MiB 1.07x 2.76 GiB/s 2.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 492.9ms 2.04 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 469.9ms 2.14 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 360.0ms 2.80 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 329.9ms 3.05 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 31.2ms 4.1ms 7.68x 43.73 MiB 2.83 MiB 0.06x 0.05 MiB/s 0.38 MiB/s
claude session --offline --json 0.00 MiB 31.4ms 4.1ms 7.62x 43.73 MiB 2.83 MiB 0.06x 0.05 MiB/s 0.38 MiB/s
codex daily --offline --json 0.00 MiB 31.0ms 3.8ms 8.13x 43.48 MiB 2.83 MiB 0.07x 0.03 MiB/s 0.22 MiB/s
codex session --offline --json 0.00 MiB 31.0ms 3.7ms 8.27x 43.48 MiB 2.83 MiB 0.07x 0.03 MiB/s 0.23 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 498.5ms 468.8ms 1.06x 262.33 MiB 262.70 MiB 1.00x 2.02 GiB/s 2.15 GiB/s
codex --offline --json 1.01 GiB 353.0ms 324.6ms 1.09x 58.20 MiB 59.83 MiB 1.03x 2.85 GiB/s 3.10 GiB/s

Artifact size

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

Use the existing fs_fixture macro for the copied branch-history regression while still exercising both single-threaded and parallel Codex loaders.
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai Updated the review follow-up in 6e48ae6 to use the existing fs_fixture! macro instead of committed fixture files, while still exercising both single-threaded and parallel Codex loader paths. Validation: cargo fmt --check, git diff --check, cargo test --manifest-path rust/Cargo.toml -p ccusage codex, plus dev-shell pre-push clippy/gitleaks/cargo-test hooks passed.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

@ryoppippi: The fs_fixture! switch is a clean improvement — all three observations from the earlier review are now resolved:

  1. Panic-safe cleanup ✅ — Fixture wraps assert_fs::TempDir, which holds the Drop impl and cleans up the temp directory even if the test panics. No more naked remove_dir_all(...).unwrap().
  2. Parallel-path coverage ✅ — for single_thread in [true, false] exercises both the sequential and parallel loader paths in a single test body.
  3. No committed fixture files ✅ — the apps/ccusage/test/fixtures/codex/sessions/branch-history/ directory is gone; all fixture data is self-contained inline in the test.

The inline JSONL strings keep the fixture data co-located with the assertions, which makes the test straightforward to read and maintain. Nothing to flag — this is in great shape.

✅ Actions performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: ec32e01062b9
Base SHA: bf84d4bc1ce8

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 bf84d4bc1ce8 428.0ms 691.0ms 32.9ms 3
PR pkg.pr.new ec32e01062b9 564.4ms 573.4ms 32.4ms 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: bf84d4bc1ce8; PR package: ec32e01062b9. 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 483.4ms 488.4ms 0.99x 265.33 MiB 255.83 MiB 0.96x 2.08 GiB/s 2.06 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 352.2ms 357.7ms 0.98x 59.33 MiB 65.20 MiB 1.10x 2.86 GiB/s 2.81 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 483.1ms 2.08 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 455.5ms 2.21 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 372.2ms 2.71 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 338.9ms 2.97 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 29.8ms 3.8ms 7.85x 43.48 MiB 2.83 MiB 0.07x 0.05 MiB/s 0.41 MiB/s
claude session --offline --json 0.00 MiB 29.6ms 3.8ms 7.78x 43.48 MiB 2.83 MiB 0.07x 0.05 MiB/s 0.41 MiB/s
codex daily --offline --json 0.00 MiB 29.0ms 3.6ms 7.99x 43.48 MiB 2.83 MiB 0.07x 0.03 MiB/s 0.24 MiB/s
codex session --offline --json 0.00 MiB 29.7ms 3.7ms 8.01x 43.48 MiB 2.83 MiB 0.07x 0.03 MiB/s 0.23 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 480.8ms 460.2ms 1.04x 261.20 MiB 264.95 MiB 1.01x 2.09 GiB/s 2.19 GiB/s
codex --offline --json 1.01 GiB 345.9ms 322.4ms 1.07x 61.20 MiB 66.20 MiB 1.08x 2.91 GiB/s 3.12 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB -0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 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: ec32e01062b9
Base SHA: bf84d4bc1ce8

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 bf84d4bc1ce8 336.5ms 347.9ms 31.1ms 3
PR pkg.pr.new ec32e01062b9 375.8ms 421.8ms 32.7ms 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: bf84d4bc1ce8; PR package: ec32e01062b9. 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 483.1ms 500.5ms 0.97x 295.58 MiB 266.95 MiB 0.90x 2.08 GiB/s 2.01 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 353.0ms 362.7ms 0.97x 59.45 MiB 60.08 MiB 1.01x 2.85 GiB/s 2.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 484.2ms 2.08 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 467.3ms 2.15 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 356.6ms 2.82 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 334.9ms 3.01 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 30.0ms 29.9ms 1.00x 43.48 MiB 43.48 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 30.3ms 30.0ms 1.01x 43.48 MiB 43.61 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
codex daily --offline --json 0.00 MiB 30.0ms 30.3ms 0.99x 43.48 MiB 43.48 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex session --offline --json 0.00 MiB 29.4ms 29.6ms 0.99x 43.48 MiB 43.61 MiB 1.00x 0.03 MiB/s 0.03 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 489.1ms 482.8ms 1.01x 257.83 MiB 260.95 MiB 1.01x 2.06 GiB/s 2.09 GiB/s
codex --offline --json 1.01 GiB 354.2ms 352.8ms 1.00x 54.08 MiB 63.83 MiB 1.18x 2.84 GiB/s 2.85 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB -0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 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: 0107c2e19757
Base SHA: bf84d4bc1ce8

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 bf84d4bc1ce8 300.4ms 434.0ms 35.6ms 3
PR pkg.pr.new 0107c2e19757 347.5ms 326.7ms 34.3ms 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: bf84d4bc1ce8; PR package: 0107c2e19757. 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 499.1ms 496.2ms 1.01x 265.33 MiB 279.95 MiB 1.06x 2.02 GiB/s 2.03 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 370.5ms 371.2ms 1.00x 68.45 MiB 59.08 MiB 0.86x 2.72 GiB/s 2.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 491.0ms 2.05 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 475.9ms 2.12 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 357.4ms 2.82 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 334.0ms 3.01 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, 3 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 31.4ms 4.2ms 7.44x 43.48 MiB 2.83 MiB 0.07x 0.05 MiB/s 0.37 MiB/s
claude session --offline --json 0.00 MiB 31.5ms 4.1ms 7.67x 43.48 MiB 2.83 MiB 0.07x 0.05 MiB/s 0.38 MiB/s
codex daily --offline --json 0.00 MiB 31.5ms 4.3ms 7.28x 43.48 MiB 2.95 MiB 0.07x 0.05 MiB/s 0.40 MiB/s
codex session --offline --json 0.00 MiB 31.8ms 4.3ms 7.42x 43.61 MiB 2.95 MiB 0.07x 0.05 MiB/s 0.40 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 499.4ms 468.3ms 1.07x 285.08 MiB 261.70 MiB 0.92x 2.02 GiB/s 2.15 GiB/s
codex --offline --json 1.01 GiB 355.0ms 327.9ms 1.08x 62.95 MiB 63.70 MiB 1.01x 2.84 GiB/s 3.07 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB +0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 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: 0107c2e19757
Base SHA: bf84d4bc1ce8

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 bf84d4bc1ce8 622.0ms 458.9ms 33.7ms 3
PR pkg.pr.new 0107c2e19757 586.5ms 439.2ms 32.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: bf84d4bc1ce8; PR package: 0107c2e19757. 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 494.0ms 507.8ms 0.97x 262.83 MiB 257.08 MiB 0.98x 2.04 GiB/s 1.98 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 361.9ms 370.3ms 0.98x 57.83 MiB 65.58 MiB 1.13x 2.78 GiB/s 2.72 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 485.8ms 2.07 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 467.7ms 2.15 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 358.9ms 2.81 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 334.5ms 3.01 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, 3 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 31.7ms 31.0ms 1.02x - - - 0.05 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 31.8ms 30.5ms 1.04x 43.61 MiB 43.48 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
codex daily --offline --json 0.00 MiB 30.9ms 30.9ms 1.00x 43.36 MiB 43.61 MiB 1.01x 0.06 MiB/s 0.06 MiB/s
codex session --offline --json 0.00 MiB 30.7ms 30.7ms 1.00x 43.48 MiB 43.61 MiB 1.00x 0.06 MiB/s 0.06 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 487.1ms 491.4ms 0.99x - 265.20 MiB - 2.07 GiB/s 2.05 GiB/s
codex --offline --json 1.01 GiB 356.9ms 356.9ms 1.00x 57.20 MiB 57.20 MiB 1.00x 2.82 GiB/s 2.82 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB +0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 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: 6e48ae651485
Base SHA: bf84d4bc1ce8

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 bf84d4bc1ce8 487.8ms 546.3ms 34.5ms 3
PR pkg.pr.new 6e48ae651485 507.1ms 530.7ms 34.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: bf84d4bc1ce8; PR package: 6e48ae651485. 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 498.6ms 505.3ms 0.99x 261.70 MiB 263.20 MiB 1.01x 2.02 GiB/s 1.99 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 369.7ms 380.7ms 0.97x 66.45 MiB 60.20 MiB 0.91x 2.72 GiB/s 2.64 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 497.9ms 2.02 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 469.3ms 2.15 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 366.7ms 2.75 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 331.6ms 3.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 31.1ms 4.1ms 7.63x 43.73 MiB 2.83 MiB 0.06x 0.05 MiB/s 0.38 MiB/s
claude session --offline --json 0.00 MiB 31.1ms 4.3ms 7.23x 43.48 MiB 2.83 MiB 0.07x 0.05 MiB/s 0.36 MiB/s
codex daily --offline --json 0.00 MiB 31.1ms 4.0ms 7.74x 43.73 MiB 2.83 MiB 0.06x 0.03 MiB/s 0.21 MiB/s
codex session --offline --json 0.00 MiB 31.8ms 4.0ms 7.90x 43.61 MiB 2.83 MiB 0.06x 0.03 MiB/s 0.21 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 508.4ms 480.6ms 1.06x 261.45 MiB 250.33 MiB 0.96x 1.98 GiB/s 2.09 GiB/s
codex --offline --json 1.01 GiB 360.0ms 327.1ms 1.10x 62.95 MiB 58.58 MiB 0.93x 2.80 GiB/s 3.08 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB +0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 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: 6e48ae651485
Base SHA: bf84d4bc1ce8

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 bf84d4bc1ce8 1.204s 464.3ms 32.5ms 3
PR pkg.pr.new 6e48ae651485 528.1ms 609.8ms 33.9ms 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: bf84d4bc1ce8; PR package: 6e48ae651485. 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 494.7ms 499.0ms 0.99x 262.70 MiB 276.58 MiB 1.05x 2.03 GiB/s 2.02 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 354.4ms 355.3ms 1.00x 66.95 MiB 56.20 MiB 0.84x 2.84 GiB/s 2.83 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 487.2ms 2.07 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 458.9ms 2.19 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 350.4ms 2.87 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 325.7ms 3.09 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 29.8ms 29.5ms 1.01x 43.48 MiB 43.48 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
claude session --offline --json 0.00 MiB 29.9ms 29.4ms 1.02x 43.48 MiB 43.48 MiB 1.00x 0.05 MiB/s 0.05 MiB/s
codex daily --offline --json 0.00 MiB 30.1ms 30.2ms 1.00x 43.36 MiB 43.48 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex session --offline --json 0.00 MiB 29.5ms 29.3ms 1.01x 43.48 MiB 43.48 MiB 1.00x 0.03 MiB/s 0.03 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 479.3ms 496.2ms 0.97x 270.95 MiB 255.83 MiB 0.94x 2.10 GiB/s 2.03 GiB/s
codex --offline --json 1.01 GiB 357.8ms 367.5ms 0.97x 64.08 MiB 61.95 MiB 0.97x 2.81 GiB/s 2.74 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 14.25 KiB 14.25 KiB +0.00 KiB 1.00x
installed native package binary 3289.49 KiB 3289.49 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 c95deda into main May 25, 2026
39 checks passed
@ryoppippi
ryoppippi deleted the codex/fix-codex-branch-dedupe branch May 25, 2026 20:08
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.

@ccusage/codex double-counts tokens for branched Codex Desktop conversations

1 participant