Repository navigation
perf(nix): build Crane layers with the binary's feature resolution - #1925
Conversation
The final `cargo build -p ccusage --bin ccusage` recompiled ccusage-core, ccusage-adapter-common and every adapter even when the foundation and adapters layers were fresh. Each layer built its crates with its own `-p` list, and Cargo unifies dependency features over the selected packages: without ccusage-pricing-snapshots in the selection, serde_json lost float_roundtrip, and ccusage-test-support pulled in rustix's fs feature, so the layer's crates got different fingerprints from the final build's. Every layer now runs the final package's own build command over a source tree where its crates are real and the rest of the workspace keeps Crane's dummy sources from the dependency layer. The dependency units and feature sets therefore match the final build exactly, and the final layer only compiles ccusage, ccusage-pricing-snapshots and the two leaf crates that were already kept out of the layers (ccusage-cli-parser, ccusage-config). Dummy-to-real transitions are caught by the fingerprint because Crane points every dummy manifest at a dummy build script. ccusage-test-support is not in the binary's graph, so the foundation layer builds it in a second invocation as before. On aarch64-darwin the final derivation's cargo step drops from 32-37s to 23-27s (three alternating --rebuild runs each). The shipped binary is unchanged apart from LC_UUID and the ad-hoc signature page hash that covers it; two --rebuild runs of the parent derivation already differ in exactly those bytes.
The foundation layer built ccusage-test-support in a second Cargo invocation for the test derivation, but nothing reused it. Its own package selection resolves cc without `parallel` and tempfile without `getrandom`, so it recompiled sqlite3-src's bundled C and a test-only dependency set that neither the binary nor `cargo test --release --workspace` reuses: the test derivation rebuilt all 110 crates it compiles, assert_fs and regex-automata included, either way. Dropping it cuts the foundation layer's cargo step from about 17.6s to 4s, and that layer gates both the binary and the config-schema preflight. The test derivation's compile time is unchanged (2m34s before, 2m35s after), and with no second invocation left the layers no longer need cargoTargetArgs.
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing: 5
✨ Finishing Touches
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. Comment |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ccusage-guide | 26be662 | Commit Preview URL Branch Preview URL |
Oct 18 2026, 03:25 PM |
ccusage
@ccusage/ccusage-darwin-arm64
@ccusage/ccusage-darwin-x64
@ccusage/ccusage-linux-arm64
@ccusage/ccusage-linux-x64
@ccusage/ccusage-win32-x64
commit: |
ccusage performance comparisonPR SHA: This compares the PR package against the configured base package on the same CI runner. Package runtime diagnosticsCompares 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
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated 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
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
ccusage performance comparisonPR SHA: This compares the Rust PR release binary against the configured base package on the same CI runner. Package runtime diagnosticsCompares 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
Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated 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
Artifact size
Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — reviewed the full PR scope (fde9835 plus 26be662) building Crane layers with the final binary's feature resolution.
- Feature-unified layer builds — each layer runs
cargoWithProfile build -p ccusage --bin ccusageoverdummySrcwith only that layer's crates made real, so dependency units match the final build. - Test-support removal — the foundation layer no longer builds
ccusage-test-supportin a second invocation; the now-unusedcargoTargetArgsplumbing is removed. - Layer wiring —
package.nix,nix/static-package.nix, andnix/darwin-x64-package.nixpassdummySrcinto the layers, and the test-support README documents its out-of-layer status.
muse-spark-1.3-contributor (free via Pullfrog for OSS) | 𝕏
Upstream tip: c76874e (2026-10-20, chore(pricing): update models.dev snapshot) Previous fork base: 0c58b88 (the upstream commit this fork was synced to) Synced 83 upstream commits on top of 0c58b88: 56 automated pricing snapshot refreshes and the following meaningful ones: 1cd29f5 chore(deps): update pnpm to v12.13.0 (ccusage#1907) e4f63ba chore(deps): update node.js to >=24.22.0 (ccusage#1908) 130e502 ci: regenerate bun.nix automatically (ccusage#1909) 259ec33 feat(adapter): report stored cost in JSON model breakdowns (ccusage#1903) c1eb448 chore: release v20.0.35 (ccusage#1901) 2a0875f ci(pricing): update snapshots on push to main and daily instead of hourly (ccusage#1914) b090428 chore(deps): update github/codeql-action action to v4.39.0 (ccusage#1912) 4dcf7f5 fix(nix): pin models-dev-gen remeda to models.dev's version and stop Renovate drift (ccusage#1915) 46edb28 fix(nix): stop the dev shell from copying the whole repository (ccusage#1917) 58ec8f1 fix(nix): let commits succeed in worktrees without a loaded dev shell (ccusage#1920) a570a6f fix(nix): vendor Cargo deps without import-from-derivation (ccusage#1918) f6d28c5 fix(antigravity): map model IDs 1418/1419 to gemini-4-argon (ccusage#1905) ce439e5 fix(antigravity): map model ID 1050 to gemini-3.1-flash-lite (ccusage#1902) e62a66f chore(deps): update pnpm to v12.14.0 (ccusage#1923) 117ae68 ci(nix): make the macOS Nix cache save a trimmed store with the Crane layers (ccusage#1921) 7a063a0 ci: shorten the Windows native build critical path (ccusage#1924) 85ebca3 perf(rust): move pricing snapshots into a leaf crate (ccusage#1922) 8fe3f47 perf(nix): build Crane layers with the binary's feature resolution (ccusage#1925) ac289aa perf(pricing): give the pricing refresh a verify-only TLS 1.3 rustls provider (ccusage#1927) d097f74 chore(deps): update rust crate rustls to 0.23.46 (ccusage#1928) f8aaf89 docs: use the compact pkg.pr.new URL for bunx previews [ci skip] (ccusage#1929) f56bb3d chore: release v20.0.36 (ccusage#1916) aaafb41 chore(deps): update dependency vitepress-plugin-group-icons to ^1.8.1 (ccusage#1931) 0861e7f fix(claude): count requestless resp_ content blocks once (ccusage#1935) 867c9f3 chore: release v20.0.37 (ccusage#1933) fa40bfd chore(deps): update songmu/tagpr action to v1.21.3 (ccusage#1937) de99d15 chore(deps): update rust crate zstd to 0.14.3 (ccusage#1936) Fork wins kept: the SQLite on-disk cache with --live-only and the per-namespace ledger, the pi adapter and its per-path namespaces, the OpenCode V2 loader, the FxHash/Cow hot paths, the table renderer, clear-cache, and the tag-only release workflow. Upstream's own release and tagpr machinery stays out. Hand-resolved conflicts: rust/adapters/claude/src/lib.rs: upstream's resp_ message-id dedupe (ccusage#1935) lands beside the fork's requestless replay and collapse_replays rules. rust/adapters/claude/src/README.md: upstream's wording for the msg_/resp_ exception. rust/Cargo.toml: zstd 0.14.3, keeping the fork's exact `=` pin style. .github/workflows/release.yaml: the fork's tag-only release, without upstream's tagpr job or the songmu/tagpr action bump. apps/ccusage/package.json, docs/package.json, package.json: keep 20.0.34; upstream's 20.0.37 bump is dropped. packages/ccusage-*/package.json (6 files): stay deleted; the fork ships no npm wrapper packages and the release workflow does not read them. rust/adapters/claude/src/daily.rs: stays deleted; the fork's daily path lives in lib.rs and shares the dedupe helper the fix changes. Fixes made while landing this sync, folded in so the merge stands green on its own: fix(ci): save the Nix store from the native build composites. The nested cache-nix-action read an empty primary-key at post-job and every native build failed; upstream's defer-save pattern is the fix. fix(rust): keep the agent-recorded cost for deleted sources. The recorded_cost ledger column carries it, so storedCost survives a deleted file. The ledger schema version stays at 2: the column is not a LedgerEntry field, so the blob layout is unchanged and the previously released binary keeps working. fix(rust): make the file fingerprint helper private, the one hawk finding. It is inherited from the pre-sync master, not introduced here. Keep 20.0.34 numbering; DO NOT push a v20.0.34 tag from this fork (release.yaml would publish fork bytes under upstream identity).

Stack created with GitHub Stacks CLI • Give Feedback 💬
Summary
The Crane artifact layers now compile the workspace crates with exactly the feature set of the final
-p ccusage --bin ccusagebuild. As a result, the final derivation no longer recompiles ccusage-core, ccusage-adapter-common, and every adapter.What Changed
nix/cargo-artifacts.nix: every layer runs the final package's own build command (commonArgs.cargoExtraArgs, which also covers--targetfor the static and cross builds). Each layer builds a source tree that starts from the dependency layer's Crane dummy source, with the layer's real crates and the real rootCargo.toml/Cargo.lockcopied on top.package.nix,nix/static-package.nix,nix/darwin-x64-package.nix: passdepsOnlyArgs.dummySrcto the layers.cargoTargetArgsis no longer needed.ccusage-test-support. The README of that crate is updated to match.Why
Cargo unifies dependency features over the packages selected with
-p. Building a layer's subset resolved different features than the final build:serde_jsonlostfloat_roundtrip, which onlyccusage-pricing-snapshotsenables.ccusage-test-supportaddedrustix/fsand changedserde_coreandcc.As a result, the layer's crates had different fingerprints from the final build's, and the final step recompiled all of them.
Cargo detects dummy-to-real transitions through the fingerprint, not mtimes. Crane points every dummy manifest at a dummy build script.
ccusage-cli-parserandccusage-configstay out of the layers, as their READMEs describe.Nothing reused the separate
ccusage-test-supportbuild:sqlite3-srcwith differentccfeatures.Testing
nix build --rebuildruns:ccusage,ccusage-pricing-snapshots,ccusage-cli-parser, andccusage-config.LC_UUIDand the code-signature page hash that covers it:--rebuildof the parent, and this branch's binary all hash to938a16b0…03de.--rebuildruns of the unchanged parent derivation already differ in exactly those bytes.--version,--help, anddaily --json --offlineproduce identical output.nix buildofchecks.aarch64-darwin.{ccusage-clippy,ccusage-hawk,config-schema}and.#ccusage-testspasses.ccusage, and the checks all evaluate.