Skip to content

perf(pricing): give the pricing refresh a verify-only TLS 1.3 rustls provider - #1927

Merged
ryoppippi merged 6 commits into
perf/align-crane-layer-featuresfrom
perf/slim-pricing-http
Oct 18, 2026
Merged

ryoppippi merged 6 commits into
perf/align-crane-layer-featuresfrom
perf/slim-pricing-http

Conversation

@ryoppippi

@ryoppippi ryoppippi commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Stack created with GitHub Stacks CLI • Give Feedback 💬

Summary

Shrinks the release binary by 66,272 bytes (3,661,648 → 3,595,376 on aarch64-darwin, -1.8%) by narrowing the rustls configuration the online pricing refresh uses. The HTTP client stays ureq; no networking code is reimplemented. The refresh behaves the same: both endpoints, ETag/304 revalidation, the 10 s deadline, the 64 MiB cap, validation, proxies, and the fallback to embedded pricing.

What Changed

  • ureq now uses rustls-no-provider and receives a verify-only rustls CryptoProvider assembled from rustls' and webpki's own ring building blocks (http/tls.rs). It uses ring's SystemRandom like rustls' ring provider, and refuses to load private keys, which drops ring's signing and PKCS#8 code.
  • Only the TLS 1.3 cipher suites and the X25519 key exchange group are offered. Both hosts negotiate TLS 1.3 with X25519.
  • Ed25519 signature verification is dropped. The CA/Browser Forum Baseline Requirements allow only RSA and ECDSA keys for publicly trusted certificates.
  • Crate READMEs are updated (ccusage-core's list also drops a stale ureq entry).

Why

An earlier revision of this PR replaced ureq with a ~600-line in-house HTTP/1.1 client and gzip decoder for a further ~215 KB. We dropped that in favor of keeping a well-maintained client: owning HTTP parsing is not worth the size for two GET requests per run. The remaining trims only select from rustls' existing building blocks.

Behavior differences (each fails safe by falling back to embedded pricing): if either host stopped offering TLS 1.3 or X25519, the refresh would use embedded pricing, and an https:// proxy with a publicly trusted certificate now also needs TLS 1.3. TLS-intercepting proxies already failed before, because only the embedded web PKI roots are trusted.

Testing

  • Real refresh with an isolated HOME and cache: both endpoints (LiteLLM and models.dev) fetched and cached; the second run left both cache files untouched with no warnings at LOG_LEVEL=5 (304 path); --offline priced the same.
  • cargo test -p ccusage (82 passed), including tests that the provider builds a client config, cannot negotiate TLS 1.2, and loads no keys.
  • Pre-push hooks: clippy -D warnings, treefmt, gitleaks, cargo test.
  • nix build .#ccusage on aarch64-darwin: 3,595,376 bytes, linking only libSystem.

@ryoppippi
ryoppippi added this pull request to stack #1926 October 18, 2026 16:24
@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 14a14c4e-a2fc-48ee-a44f-bbf4496779ef
📥 Commits

Reviewing files that changed from the base of the PR and between 26be662 and 4f483cf.

⛔ Files ignored due to path filters: 1
  • rust/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing: 6
  • rust/Cargo.toml
  • rust/crates/ccusage-core/README.md
  • rust/crates/ccusage/Cargo.toml
  • rust/crates/ccusage/README.md
  • rust/crates/ccusage/src/http.rs
  • rust/crates/ccusage/src/http/tls.rs
+--------------------------------------------------+
| Deploying the charm offensive against your bugs. |
+--------------------------------------------------+
  \
   \     /)/)
        ( '')
        /  |
      o(___)
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@ryoppippi ryoppippi changed the title perf/slim pricing http perf(pricing): slim the pricing refresh HTTP/TLS stack Oct 18, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 18, 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 4f483cf Commit Preview URL

Branch Preview URL
Oct 18 2026, 04:53 PM

@pkg-pr-new

pkg-pr-new Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

ccusage

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

@ccusage/ccusage-darwin-arm64

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

@ccusage/ccusage-darwin-x64

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

@ccusage/ccusage-linux-arm64

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

@ccusage/ccusage-linux-x64

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

@ccusage/ccusage-win32-x64

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

commit: 4f483cf

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 92dd409cc27f
Base SHA: 26be66213d6a

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 403.3ms 2.50 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 380.8ms 2.64 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 150.7ms 6.68 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 123.9ms 8.13 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 native ccusage binary 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 45.2ms 19.3ms 2.34x 55.75 MiB 22.95 MiB 0.41x 0.03 MiB/s 0.08 MiB/s
claude session --offline --json 0.00 MiB 40.2ms 13.1ms 3.06x 56.00 MiB 22.95 MiB 0.41x 0.04 MiB/s 0.12 MiB/s
codex daily --offline --json 0.00 MiB 39.2ms 13.1ms 3.00x 55.50 MiB 28.95 MiB 0.52x 0.02 MiB/s 0.07 MiB/s
codex session --offline --json 0.00 MiB 36.7ms 13.7ms 2.68x 55.50 MiB 28.95 MiB 0.52x 0.02 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 383.3ms 361.2ms 1.06x 943.10 MiB 956.84 MiB 1.01x 2.63 GiB/s 2.79 GiB/s
codex --offline --json 1.01 GiB 156.3ms 126.2ms 1.24x 547.45 MiB 503.17 MiB 0.92x 6.44 GiB/s 7.98 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 24.03 KiB 24.03 KiB +0.00 KiB 1.00x
installed native package binary 4906.34 KiB 4592.34 KiB -314.00 KiB 1.07x

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: 92dd409cc27f
Base SHA: 26be66213d6a

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 392.8ms 2.56 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 362.9ms 2.77 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 141.1ms 7.14 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 122.5ms 8.22 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 42.5ms 37.4ms 1.14x 55.50 MiB 55.25 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
claude session --offline --json 0.00 MiB 60.6ms 65.6ms 0.92x 55.50 MiB 55.50 MiB 1.00x 0.03 MiB/s 0.02 MiB/s
codex daily --offline --json 0.00 MiB 59.1ms 66.5ms 0.89x 55.50 MiB 55.50 MiB 1.00x 0.01 MiB/s 0.01 MiB/s
codex session --offline --json 0.00 MiB 51.2ms 57.9ms 0.89x 55.25 MiB 55.50 MiB 1.00x 0.02 MiB/s 0.01 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 567.5ms 512.3ms 1.11x 919.09 MiB 931.09 MiB 1.01x 1.77 GiB/s 1.97 GiB/s
codex --offline --json 1.01 GiB 157.8ms 152.5ms 1.04x 543.44 MiB 507.17 MiB 0.93x 6.38 GiB/s 6.60 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 24.03 KiB 24.03 KiB +0.00 KiB 1.00x
installed native package binary 4906.34 KiB 4592.34 KiB -314.00 KiB 1.07x

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: 79a90a6820cc
Base SHA: 26be66213d6a

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 378.8ms 2.66 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 356.9ms 2.82 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 169.9ms 5.93 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 204.4ms 4.92 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 native ccusage binary 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 41.0ms 19.9ms 2.06x 55.75 MiB 22.95 MiB 0.41x 0.04 MiB/s 0.08 MiB/s
claude session --offline --json 0.00 MiB 35.1ms 13.9ms 2.53x 55.50 MiB 22.95 MiB 0.41x 0.04 MiB/s 0.11 MiB/s
codex daily --offline --json 0.00 MiB 41.8ms 14.6ms 2.87x 55.50 MiB 28.96 MiB 0.52x 0.02 MiB/s 0.06 MiB/s
codex session --offline --json 0.00 MiB 39.0ms 13.7ms 2.85x 55.75 MiB 28.95 MiB 0.52x 0.02 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 392.2ms 362.8ms 1.08x 935.10 MiB 931.09 MiB 1.00x 2.57 GiB/s 2.78 GiB/s
codex --offline --json 1.01 GiB 144.8ms 127.3ms 1.14x 513.43 MiB 505.43 MiB 0.98x 6.95 GiB/s 7.91 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 24.03 KiB 24.03 KiB +0.00 KiB 1.00x
installed native package binary 4906.34 KiB 4592.72 KiB -313.63 KiB 1.07x

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: 79a90a6820cc
Base SHA: 26be66213d6a

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 380.3ms 2.65 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 336.0ms 3.00 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 138.2ms 7.28 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 115.7ms 8.70 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 45.2ms 37.3ms 1.21x 55.00 MiB 55.25 MiB 1.00x 0.03 MiB/s 0.04 MiB/s
claude session --offline --json 0.00 MiB 35.8ms 37.7ms 0.95x 55.25 MiB 55.50 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
codex daily --offline --json 0.00 MiB 36.2ms 36.1ms 1.00x 55.50 MiB 55.50 MiB 1.00x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 35.0ms 34.5ms 1.01x 55.25 MiB 55.50 MiB 1.00x 0.02 MiB/s 0.02 MiB/s

Large real-world-shaped fixture performance

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

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 368.4ms 375.4ms 0.98x 937.08 MiB 953.08 MiB 1.02x 2.73 GiB/s 2.68 GiB/s
codex --offline --json 1.01 GiB 141.2ms 141.6ms 1.00x 503.43 MiB 515.42 MiB 1.02x 7.13 GiB/s 7.11 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 24.03 KiB 24.03 KiB +0.00 KiB 1.00x
installed native package binary 4906.34 KiB 4592.72 KiB -313.63 KiB 1.07x

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

ureq's `rustls` feature installs rustls' own ring provider, whose key
loader keeps ring's RSA, ECDSA and Ed25519 signing code and PKCS#8
parsing in the binary. The pricing refresh only verifies servers and
never presents a client certificate, so none of that is reachable in
practice, but LTO cannot prove it.

The binary now enables ureq's `rustls-no-provider` and
`rustls-webpki-roots` features instead and hands ureq a provider built
from the same ring cipher suites, key exchange groups and signature
verification algorithms, with system randomness from ring and a key
loader that always fails. Negotiation and certificate verification are
unchanged.

On aarch64-darwin the release binary's sections shrink by 35,090 bytes
(3,635,724 -> 3,600,634); the file shrinks by 66,192 bytes because the
__TEXT segment drops a page.
raw.githubusercontent.com and models.dev both negotiate TLS 1.3
(checked with `openssl s_client -tls1_3`; both pick X25519 and a TLS 1.3
AEAD suite), so the six TLS 1.2 suites only keep their key schedule,
PRF and AEAD glue in the binary. The provider now lists the three TLS
1.3 suites alone, which also means rustls cannot fall back to TLS 1.2.

The one setup that could need TLS 1.2 is a TLS-intercepting middlebox,
and those already fail certificate verification because the client
trusts only the embedded web PKI roots. CONNECT proxies tunnel the
origin's own handshake and are unaffected.

ureq still enables rustls' `tls12` feature, so the TLS 1.2 handshake
state machine stays compiled in for now.

Release binary sections on aarch64-darwin: 3,600,634 -> 3,593,067
(-7,567 bytes).
Both pricing hosts select X25519 when it is offered, so the P-256 and
P-384 ECDH groups only add their key generation and agreement glue. The
provider now offers X25519 alone. ring's P-256 and P-384 arithmetic and
its precomputed P-256 table stay: certificate verification still needs
them for the ECDSA chain models.dev serves (WE1 -> GTS Root R4).

Release binary sections on aarch64-darwin: 3,593,067 -> 3,586,978
(-6,089 bytes).
The CA/Browser Forum Baseline Requirements only permit RSA and ECDSA
subscriber and CA keys, and none of the embedded web PKI roots is an
Ed25519 key, so no chain the pricing client can accept and no TLS 1.3
CertificateVerify from such a chain uses Ed25519. Dropping it from the
verification algorithms lets LTO discard ring's Ed25519 verifier. The
X25519 base-point table stays, since key exchange still uses it.

Release binary sections on aarch64-darwin: 3,586,978 -> 3,579,431
(-7,547 bytes); the file drops another 16 KiB page.
The ccusage README now lists http.rs and http/ and the ureq, rustls, ring and rustls-webpki dependencies it pulls in. ccusage-core's list drops ureq, which it has not depended on since the client moved into the binary, and gains miniz_oxide, which it does use.
@ryoppippi
ryoppippi force-pushed the perf/slim-pricing-http branch from 79a90a6 to 4f483cf Compare October 18, 2026 16:53
@ryoppippi ryoppippi changed the title perf(pricing): slim the pricing refresh HTTP/TLS stack perf(pricing): give the pricing refresh a verify-only TLS 1.3 rustls provider Oct 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 4f483cf3dedf
Base SHA: 26be66213d6a

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 376.9ms 2.67 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 341.3ms 2.95 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 145.6ms 6.91 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 115.8ms 8.69 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 native ccusage binary 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 44.0ms 12.8ms 3.44x 55.25 MiB 22.96 MiB 0.42x 0.04 MiB/s 0.12 MiB/s
claude session --offline --json 0.00 MiB 42.9ms 12.8ms 3.35x 56.00 MiB 22.96 MiB 0.41x 0.04 MiB/s 0.12 MiB/s
codex daily --offline --json 0.00 MiB 37.8ms 12.8ms 2.95x 56.00 MiB 28.96 MiB 0.52x 0.02 MiB/s 0.07 MiB/s
codex session --offline --json 0.00 MiB 37.7ms 12.6ms 2.99x 55.50 MiB 28.96 MiB 0.52x 0.02 MiB/s 0.07 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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published native ccusage binary 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 365.6ms 355.0ms 1.03x 959.10 MiB 945.09 MiB 0.99x 2.75 GiB/s 2.84 GiB/s
codex --offline --json 1.01 GiB 147.4ms 131.0ms 1.12x 511.43 MiB 509.43 MiB 1.00x 6.83 GiB/s 7.68 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 24.03 KiB 24.03 KiB +0.00 KiB 1.00x
installed native package binary 4906.34 KiB 4830.03 KiB -76.31 KiB 1.02x

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: 4f483cf3dedf
Base SHA: 26be66213d6a

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

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, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 370.4ms 2.72 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 333.6ms 3.02 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 126.5ms 7.96 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 102.9ms 9.78 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 45.2ms 43.7ms 1.04x 55.75 MiB 55.50 MiB 1.00x 0.03 MiB/s 0.04 MiB/s
claude session --offline --json 0.00 MiB 43.1ms 39.1ms 1.10x 55.50 MiB 55.25 MiB 1.00x 0.04 MiB/s 0.04 MiB/s
codex daily --offline --json 0.00 MiB 38.2ms 39.3ms 0.97x 55.50 MiB 55.25 MiB 1.00x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 38.5ms 37.3ms 1.03x 55.50 MiB 55.75 MiB 1.00x 0.02 MiB/s 0.02 MiB/s

Large real-world-shaped fixture performance

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

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2597 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 358.7ms 346.7ms 1.03x 955.09 MiB 965.09 MiB 1.01x 2.81 GiB/s 2.90 GiB/s
codex --offline --json 1.01 GiB 124.8ms 143.7ms 0.87x 503.43 MiB 503.42 MiB 1.00x 8.07 GiB/s 7.00 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 24.03 KiB 24.03 KiB +0.00 KiB 1.00x
installed native package binary 4906.34 KiB 4830.03 KiB -76.31 KiB 1.02x

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 marked this pull request as ready for review October 18, 2026 17:03
@ryoppippi
ryoppippi merged commit ac289aa into main Oct 18, 2026
45 of 46 checks passed
@ryoppippi
ryoppippi deleted the perf/slim-pricing-http branch October 18, 2026 17:03

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

ℹ️ Minor suggestions only — the narrowing is sound and fail-safe; two small follow-ups below.

Reviewed changes
Reviewed the full stack (6 commits) replacing rustls' own ring provider with a hand-assembled verify-only provider for the pricing refresh:

  • Verify-only provider — new http/tls.rs builds a CryptoProvider from rustls/ring primitives with ring SystemRandom and a key loader that always fails; http.rs hands it to ureq, which moves from the rustls feature to rustls-no-provider + rustls-webpki-roots.
  • TLS 1.3-only suites — only the three TLS 1.3 cipher suites are offered, with a test pinning that TLS 1.2 cannot negotiate.
  • X25519-only key exchange — P-256/P-384 ECDH groups dropped while their arithmetic stays for ECDSA chain verification.
  • No Ed25519 verification — dropped from all and mapping, order otherwise preserved from rustls' ring provider.
  • Dependency rewiring — workspace gains ring/rustls/rustls-webpki specs consumed directly by the binary crate; lockfile shows edge-only changes, no version bumps.
  • README updates — ccusage documents the client and its deps; ccusage-core drops a stale ureq entry and gains the already-real miniz_oxide entry.

Verification, timeouts, ETag/304 caching, and the embedded-pricing fallback are untouched, and every narrowing fails safe into that fallback. No correctness, security, or release-risk concerns found.

ℹ️ Proxy doc names TLS 1.3 but not X25519

The doc comment on provider() in rust/crates/ccusage/src/http/tls.rs says an https:// proxy with a publicly trusted certificate now needs TLS 1.3, but an https:// proxy that terminates TLS without X25519 would fail the handshake the same way, since kx_groups is X25519-only. Worth naming both so the documented proxy requirement matches the offered surface.

ℹ️ X25519-only and Ed25519-absence are unpinned by tests

TLS 1.2 exclusion has a regression test (provider_cannot_negotiate_tls_1_2), but neither the X25519-only kx_groups nor the Ed25519 removal from SIGNATURE_ALGORITHMS does. A later edit widening either would silently undo the size win. Consider pinning the single group and the Ed25519 absence next to that test.

Pullfrog  | Fix it ➔ | View workflow run | Using muse-spark-1.3-contributor (free via Pullfrog for OSS) | 𝕏

Buster210 added a commit to Buster210/ccusage that referenced this pull request Oct 20, 2026
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).
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