Skip to content

fix: route benchmark registry tarballs through proxy#12257

Merged
zkochan merged 1 commit into
mainfrom
codex/benchmark-registry-public-url-proxy
Jun 7, 2026
Merged

fix: route benchmark registry tarballs through proxy#12257
zkochan merged 1 commit into
mainfrom
codex/benchmark-registry-public-url-proxy

Conversation

@zkochan

@zkochan zkochan commented Jun 7, 2026

Copy link
Copy Markdown
Member

Summary

  • let registry-mock receive an optional public URL for pnpr --public-url
  • in integrated-benchmark Verdaccio mode with registry latency or bandwidth enabled, run the mock registry on a private upstream port and bind the latency proxy to the configured public registry port
  • keep external virtual registry wrapping in WorkEnv and add focused latency-proxy tests

This fixes the benchmark topology where packuments were fetched through the emulated registry link but dist.tarball URLs still pointed at the raw mock-registry port, so tarball downloads bypassed the benchmark latency/bandwidth proxy.

Tests

  • cargo test -p pacquet-integrated-benchmark latency_proxy
  • cargo check -p pacquet-registry-mock -p pacquet-integrated-benchmark
  • cargo clippy -p pacquet-registry-mock -p pacquet-integrated-benchmark --all-targets -- --deny warnings
  • cargo test -p pacquet-registry-mock
  • pre-push hook completed: TypeScript compile/lint, Rust fmt/doc/dylint, taplo format check

Written by an agent (Codex, GPT-5).

Summary by CodeRabbit

  • New Features

    • Integrated benchmark now optionally fronts the registry with a local proxy that applies configurable latency and bandwidth constraints.
    • Registry mock now supports optional public URL configuration for proxy scenarios.
  • Tests

    • Added test coverage for proxy socket address binding and bandwidth-to-rate conversion.

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: da4465a1-97e1-4294-b1f4-6d00fdc3b5ad

📥 Commits

Reviewing files that changed from the base of the PR and between 75bf4bf and d550f3d.

📒 Files selected for processing (7)
  • pacquet/tasks/integrated-benchmark/src/latency_proxy.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • pacquet/tasks/registry-mock/src/main.rs
  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: windows-latest / Node.js 22.13.0 / Test
  • GitHub Check: Run benchmark on ubuntu-latest
🧰 Additional context used
📓 Path-based instructions (1)
pacquet/**/*.rs

📄 CodeRabbit inference engine (pacquet/AGENTS.md)

pacquet/**/*.rs: Log emissions are part of matching pnpm — when porting a function that fires pnpm:<channel> events through globalLogger, logger.debug(...), or streamParser.write(...), mirror the call site, payload, and ordering so @pnpm/cli.default-reporter parses pacquet's NDJSON the same way
Declare a newtype wrapper for branded string types instead of collapsing the brand into a plain String or &str in Rust
If upstream TypeScript always validates before construction of a branded string, validate in the Rust wrapper too via TryFrom<String> and/or FromStr and do not provide an infallible public constructor
If upstream TypeScript never validates a branded string, just brand for type-safety in Rust by exposing an infallible From<String> constructor
If upstream TypeScript occasionally constructs a branded string without validation, expose from_str_unchecked in Rust as an escape hatch alongside the validating constructor
Match upstream serde behavior for branded strings crossing JSON, YAML, or INI boundaries by using #[serde(try_from = "String")] for deserialization and #[serde(into = "String")] for serialization
Derive simple conversions for branded strings using #[derive(derive_more::From)] and #[derive(derive_more::Into)] instead of handwriting impl blocks; use manual impl only when conversion needs custom logic
Model TypeScript string literal unions (like 'auto' | 'always' | 'never') as Rust enums instead of newtype wrappers, since the set of valid values is closed
Treat TypeScript string template literal types (like `${string}@${string}`) the same as branded string types in Rust, using a newtype wrapper with validation
Follow the code style guide in CODE_STYLE_GUIDE.md — imports, modules, naming, ownership and borrowing, parameter type selection, trait bounds, pattern matching, pipe-trait, error handling, test layout, and cloning of Arc and Rc
Choose owned vs. borrowed parameters to minimize copies; widen to t...

Files:

  • pacquet/tasks/registry-mock/src/main.rs
  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
🧠 Learnings (25)
📓 Common learnings
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12154
File: pacquet/tasks/integrated-benchmark/src/work_env.rs:401-423
Timestamp: 2026-06-03T09:27:50.473Z
Learning: In `pnpm/pnpm` (pacquet Rust port), `pick_unused_port()` from `pacquet-registry-mock` is the established repo-wide pattern for choosing a port when spawning child processes (pnpr server, registry mock) in tests and benchmarks. The alternative of `--listen 127.0.0.1:0` (ephemeral port) is not currently viable because pnpr's `serve()` logs the *requested* `config.listen` address rather than `listener.local_addr()`, so the actual bound port cannot be discovered without a pnpr-side change. Do not flag `pick_unused_port()` usage in benchmark orchestration code as a TOCTOU bug without acknowledging this constraint.
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11895
File: pnpm/test/deploy.ts:91-95
Timestamp: 2026-05-24T08:18:06.019Z
Learning: In the pnpm/pnpm repository, integration tests that hit the real `registry.npmjs.org` (e.g., for `pacquet` or `pnpm/pacquet`) do NOT use a runtime env-var gate (such as `PNPM_RUN_PUBLIC_REGISTRY_TESTS`). They simply pass `--config.registry=https://registry.npmjs.org/` directly to `execPnpm` and set a higher timeout. This is the established pattern, as seen in `pnpm/test/install/pacquet.ts` and `pnpm/test/deploy.ts`. Do not suggest adding env-var guards for these tests.
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/tests/**/*.rs : Tests that need the mocked registry should start `pnpr` through `pacquet-testing-utils`; `cargo test` / `cargo nextest run` should not require a separate `just registry-mock launch` step
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11773
File: pacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs:115-117
Timestamp: 2026-05-20T20:41:30.632Z
Learning: In the pacquet Rust port of pnpm, the `is_http_url` helper in `pacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs` intentionally uses `bare.starts_with("http:") || bare.starts_with("https:")` (not `"http://"` / `"https://"`) to match upstream pnpm's `startsWith('http:')` / `startsWith('https:')` check byte-for-byte. Pacquet's cardinal rule (pacquet/AGENTS.md) requires matching pnpm even on quirks; malformed non-URL inputs are rejected downstream by `reqwest::Url::parse` as a `ResolveError`.
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12189
File: pacquet/crates/cli/src/cli_args/install.rs:0-0
Timestamp: 2026-06-04T14:55:52.163Z
Learning: In `pacquet/crates/cli/src/cli_args/install.rs` (pnpm/pnpm repo), the `install_via_pnpr` function intentionally forwards the **full** `state.config.auth_headers` map to the pnpr server (not filtered to only the declared default/named registries). This is required for correctness: transitive dependencies can be scope-routed to registries not in the explicit registry list, or pinned to tarball URLs on hosts present in `.npmrc` but not a declared registry. Filtering to the declared registries silently drops tokens those sub-dependencies need, causing 401s on the server. pnpr uses the forwarded map to attach the right token per fetched URL exactly as a local install does (`AuthHeaders::for_url`). The pnpr-server's own credential is sent separately in the `Authorization` header and is excluded from the body map. Do NOT flag this as a credential-leakage issue — the rationale is documented in a comment at both call sites.
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/tests/**/*.rs : Tests that need the mocked registry should start `pnpr` through `pacquet-testing-utils`; `cargo test` / `cargo nextest run` should not require a separate `just registry-mock launch` step

Applied to files:

  • pacquet/tasks/registry-mock/src/main.rs
  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/tests/**/*.rs : Prefer real fixtures over dependency-injection seams — use `tempfile::TempDir`, the mocked registry, or integration tests spawning the actual binary for happy paths and most error paths; use the DI seam only for filesystem error kinds, deterministic time, shared process-global state, or external-service happy paths

Applied to files:

  • pacquet/tasks/registry-mock/src/main.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/tests/**/*.rs : Use snapshot tests with `insta` and carefully review diffs when intentional changes alter snapshots; accept with `cargo insta review` only after careful review

Applied to files:

  • pacquet/tasks/registry-mock/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
📚 Learning: 2026-05-20T23:07:58.444Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11784
File: pacquet/crates/resolving-deps-resolver/src/hoist_peers.rs:120-133
Timestamp: 2026-05-20T23:07:58.444Z
Learning: When reviewing code in this pacquet Rust port, follow the upstream pnpm compatibility rule: only match pnpm’s behavior exactly. Do not propose review changes that intentionally deviate from pnpm’s documented/observed behavior, even if pnpm appears buggy. If you identify a real bug in pnpm behavior, the review should prioritize fixing it upstream in pnpm first, and avoid implementing a pnpm-behavior workaround here unless the same fix has already landed upstream.

Applied to files:

  • pacquet/tasks/registry-mock/src/main.rs
  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-06-06T18:58:37.156Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12243
File: pacquet/crates/package-manager/src/install_package_by_snapshot.rs:319-322
Timestamp: 2026-06-06T18:58:37.156Z
Learning: When reviewing Rust code, do not assume `matches!(expr, Pattern(_))` will move out of `expr` if `Pattern(_)` contains no by-value bindings. `matches!` desugars to a `match` that auto-borrows the scrutinee for discrimination, so even if `expr` is a non-`Copy` value behind a shared reference (e.g., `&T`), the macro should not move-out of the borrowed data purely due to `matches!`. Treat `matches!(&expr, Pattern(_))` as a readability/clarity improvement, not a correctness requirement. Only flag potential move-out-of-borrow risks when the pattern includes by-value bindings that would require moving the matched value.

Applied to files:

  • pacquet/tasks/registry-mock/src/main.rs
  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-06-03T09:27:50.473Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12154
File: pacquet/tasks/integrated-benchmark/src/work_env.rs:401-423
Timestamp: 2026-06-03T09:27:50.473Z
Learning: In `pnpm/pnpm` (pacquet Rust port), `pick_unused_port()` from `pacquet-registry-mock` is the established repo-wide pattern for choosing a port when spawning child processes (pnpr server, registry mock) in tests and benchmarks. The alternative of `--listen 127.0.0.1:0` (ephemeral port) is not currently viable because pnpr's `serve()` logs the *requested* `config.listen` address rather than `listener.local_addr()`, so the actual bound port cannot be discovered without a pnpr-side change. Do not flag `pick_unused_port()` usage in benchmark orchestration code as a TOCTOU bug without acknowledging this constraint.

Applied to files:

  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-19T07:12:00.339Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11734
File: installing/deps-installer/src/install/runPacquet.ts:48-51
Timestamp: 2026-05-19T07:12:00.339Z
Learning: In pnpm/pnpm, `runPacquet.ts` spawns the pacquet bin via `spawn(process.execPath, [pacquetBin, ...args], ...)` rather than `spawn(pacquetBin, args, ...)`. This is intentional: `pacquetBin` (`node_modules/.pnpm-config/pacquet/bin/pacquet`) is a Node wrapper script (starts with `#!/usr/bin/env node`) that resolves the platform-specific native binary at runtime. Spawning it directly works on Unix via shebang but silently breaks on Windows where shebangs are not honoured; using `process.execPath` ensures the launcher runs under the same Node binary on every platform. Do not flag this as a bug.

Applied to files:

  • pacquet/tasks/registry-mock/src/mock_instance.rs
📚 Learning: 2026-05-24T08:18:06.019Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11895
File: pnpm/test/deploy.ts:91-95
Timestamp: 2026-05-24T08:18:06.019Z
Learning: In the pnpm/pnpm repository, integration tests that hit the real `registry.npmjs.org` (e.g., for `pacquet` or `pnpm/pacquet`) do NOT use a runtime env-var gate (such as `PNPM_RUN_PUBLIC_REGISTRY_TESTS`). They simply pass `--config.registry=https://registry.npmjs.org/` directly to `execPnpm` and set a higher timeout. This is the established pattern, as seen in `pnpm/test/install/pacquet.ts` and `pnpm/test/deploy.ts`. Do not suggest adding env-var guards for these tests.

Applied to files:

  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-06-06T22:48:27.363Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-06-06T22:48:27.363Z
Learning: Keep pnpm and pacquet in sync — any user-visible change (CLI flags, defaults, environment-variable handling, lockfile/manifest/state-file format, error codes and messages, log emissions, store layout, hook semantics) must land in both the TypeScript pnpm CLI and the Rust pacquet port in the same PR

Applied to files:

  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
📚 Learning: 2026-05-20T20:41:30.632Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11773
File: pacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs:115-117
Timestamp: 2026-05-20T20:41:30.632Z
Learning: In the pacquet Rust port of pnpm, the `is_http_url` helper in `pacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs` intentionally uses `bare.starts_with("http:") || bare.starts_with("https:")` (not `"http://"` / `"https://"`) to match upstream pnpm's `startsWith('http:')` / `startsWith('https:')` check byte-for-byte. Pacquet's cardinal rule (pacquet/AGENTS.md) requires matching pnpm even on quirks; malformed non-URL inputs are rejected downstream by `reqwest::Url::parse` as a `ResolveError`.

Applied to files:

  • pacquet/tasks/registry-mock/src/mock_instance.rs
  • pacquet/tasks/registry-mock/src/pnpr_command.rs
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Match how the same feature is implemented in the TypeScript pnpm CLI — any change in pacquet must match pnpm's behavior, logic, edge cases, config resolution, error messages, file/lockfile formats, and existing tests

Applied to files:

  • pacquet/tasks/registry-mock/src/mock_instance.rs
📚 Learning: 2026-05-18T20:35:22.917Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11729
File: pacquet/crates/resolving-npm-resolver/src/fetch_attestation_published_at.rs:55-57
Timestamp: 2026-05-18T20:35:22.917Z
Learning: In `pacquet/crates/resolving-npm-resolver/src/fetch_attestation_published_at.rs`, the npm attestation endpoint (`/-/npm/v1/attestations/{pkg_name}@{version}`) intentionally does NOT percent-encode the package name — the endpoint accepts literal `/` in scoped package names (e.g. `scope/pkg`). This matches upstream pnpm's `fetchAttestationPublishedAt.ts` behavior. Do not flag missing URL encoding here. By contrast, the full-metadata fetch paths (`fetch_full_metadata`, `fetch_full_metadata_cached`) DO percent-encode via the `registry_url::to_registry_url` helper, matching upstream's `toUri` behavior.

Applied to files:

  • pacquet/tasks/registry-mock/src/pnpr_command.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:24.797Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.797Z
Learning: Applies to pnpr/**/pnpr/crates/**/Cargo.toml : New registry-only crates must be placed under pnpr/crates/<short-name>/ and named pnpr-<short-name> in Cargo.toml, never using the pacquet- prefix

Applied to files:

  • pacquet/tasks/registry-mock/src/pnpr_command.rs
📚 Learning: 2026-05-24T21:11:04.272Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11915
File: pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs:553-617
Timestamp: 2026-05-24T21:11:04.272Z
Learning: In the pacquet Rust port (pnpm/pnpm repo), the `ResolvedPackage.optional` AND-folding on revisit intentionally mirrors pnpm's `resolveDependencies.ts:1627-1648` behavior: only the directly-revisited package's `optional` flag is updated; transitive descendants are not re-walked. pnpm CLI corrects stale optional flags downstream via `copyDependencySubGraph` BFS in `lockfile/pruner/src/index.ts:160-205`, which tracks a `nonOptional` set and re-stamps any package reachable by an all-non-optional path. Pacquet does not yet have this pruner equivalent, so the stale flags flow directly through `dependencies_graph_to_lockfile.rs:409` → `create_virtual_store.rs:762` → `installability.rs:394`. A follow-up to port `copyDependencySubGraph` is planned; until then, do not flag the resolver-layer optional propagation gap as a bug in pacquet PRs — it is intentional parity with pnpm's resolver layer.

Applied to files:

  • pacquet/tasks/registry-mock/src/pnpr_command.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
📚 Learning: 2026-05-29T18:03:24.797Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.797Z
Learning: Applies to pnpr/**/pnpr/crates/**/Cargo.toml : Cargo.toml files for new registry-only crates must use the pnpr- prefix for the package name

Applied to files:

  • pacquet/tasks/registry-mock/src/pnpr_command.rs
📚 Learning: 2026-05-25T14:58:11.105Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11931
File: pacquet/crates/resolving-npm-resolver/src/create_npm_resolution_verifier.rs:560-589
Timestamp: 2026-05-25T14:58:11.105Z
Learning: In `pacquet/crates/resolving-npm-resolver/src/create_npm_resolution_verifier.rs`, all per-`(registry, name[, version])` caches in `NpmResolutionVerifier` (`published_at`, `full_meta`, `full_meta_for_trust`, `abbreviated_meta`, `local_meta`) intentionally use the same pattern: lock → miss-check → release lock → await fetch/load → re-acquire lock → insert. This uniform pattern is deliberate; do not flag individual caches for using it. The known follow-up improvement (replacing the pattern with `tokio::sync::OnceCell` per key inside a `Mutex<HashMap<…>>`) is tracked as a future structural change to cover all five caches simultaneously.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:24.797Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.797Z
Learning: Prefer existing pacquet-* crates over writing new code; check pacquet-tarball, pacquet-crypto-hash, pacquet-crypto-shasums-file, pacquet-package-manifest, pacquet-network, pacquet-registry, pacquet-fs, and pacquet-diagnostics before implementing non-trivial functionality

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
📚 Learning: 2026-06-04T14:40:29.444Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12189
File: pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs:435-439
Timestamp: 2026-06-04T14:40:29.444Z
Learning: In `pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs` (pnpm/pnpm repo), the pnpr install accelerator always invokes `Install` with `lockfile_only: true` (hard-coded in `pnpr/crates/pnpr/src/install_accelerator/resolve.rs`). Under `lockfile_only: true`:
1. The `PrefetchingResolver` wrapper is skipped — the bare `inner_resolver` is used instead, so `PrefetchContext { config }` is never constructed.
2. The function returns before `CreateVirtualStore` is reached, so `install_package_by_snapshot` and its `config.auth_headers` fetch path are never hit.
pnpr's tarball fetch is handled separately in `resolve::fetch_uncached`, which independently receives the request-scoped `auth_headers`. Therefore, `auth_override` only needs to be threaded into the resolver-side components (NpmResolver, TarballResolver, NamedRegistryResolver) — not into PrefetchingResolver or CreateVirtualStore — on the pnpr path. For local installs (`lockfile_only: false`), `auth_override` is always `None` a...

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/tests/**/*.rs : Port relevant pnpm tests to Rust tests whenever they translate when porting behavior from pnpm

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Consult `plans/TEST_PORTING.md` before adding ported tests and update its checkboxes as items land; use `known_failures` modules and `pacquet_testing_utils::allow_known_failure!` at the not-yet-implemented boundary

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/*.rs : Tests are documentation — do not duplicate test scenarios, edge cases, failure modes, or worked examples in prose when they are already captured by tests

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
📚 Learning: 2026-06-02T13:18:30.659Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12134
File: pacquet/crates/resolving-npm-resolver/src/create_npm_resolution_verifier.rs:311-325
Timestamp: 2026-06-02T13:18:30.659Z
Learning: In pacquet's lockfile resolution verifier (`pacquet/crates/resolving-npm-resolver/src/create_npm_resolution_verifier.rs`), URL-keyed tarball dependencies do NOT need a separate `non_semver_version` field in `VerifyCtx`. Unlike the TypeScript side (which derives `version` from `snapshot.version` and threads `nonSemverVersion` separately), pacquet's `collect_candidates` takes `version` from the lockfile key suffix. For a URL-keyed dep the key is `name@<url>`, so `ctx.version` is the URL string, which fails `node_semver::Version::parse(ctx.version)` and the existing guard `if node_semver::Version::parse(ctx.version).is_err() { return ResolutionVerification::Ok; }` already skips the registry lookup correctly. Adding a `non_semver_version` field to `VerifyCtx` for this purpose would be inert.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/tests/**/*.rs : Prefer `#[cfg_attr(target_os = "windows", ignore = "...")]` (or matching `#[cfg(unix)]` gates) over runtime probe-and-skip helpers for platform-locked tools

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.372Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/tests/**/*.rs : Tests must not be tolerant of missing build/runtime environment by silently returning early when a tool isn't found — let the test panic when a required tool is absent

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
🔇 Additional comments (24)
pacquet/tasks/integrated-benchmark/src/latency_proxy.rs (4)

28-28: LGTM!


61-63: LGTM!


65-82: LGTM!


84-94: LGTM!

pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs (2)

9-34: LGTM!


36-42: LGTM!

pacquet/tasks/registry-mock/src/pnpr_command.rs (3)

61-66: LGTM!


67-67: LGTM!

Also applies to: 83-90


103-103: LGTM!

pacquet/tasks/registry-mock/src/mock_instance.rs (3)

37-37: LGTM!


75-75: LGTM!

Also applies to: 88-88


135-135: LGTM!

pacquet/tasks/registry-mock/src/main.rs (1)

33-33: LGTM!

pacquet/tasks/integrated-benchmark/src/work_env.rs (5)

6-6: LGTM!


32-35: LGTM!


560-564: LGTM!


598-608: LGTM!


627-635: LGTM!

pacquet/tasks/integrated-benchmark/src/main.rs (6)

12-16: LGTM!


54-69: LGTM!


98-117: LGTM!


160-160: LGTM!


178-178: LGTM!


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

Use tokio::time::Duration to match MockInstanceOptions::retry_delay type.

Line 86 constructs Duration::from_millis(500) using std::time::Duration (imported at line 15), but MockInstanceOptions::retry_delay expects tokio::time::Duration (imported in mock_instance.rs at line 12). The types are distinct and not interchangeable.

🔧 Proposed fix
-                    retry_delay: Duration::from_millis(500),
+                    retry_delay: tokio::time::Duration::from_millis(500),
⛔ Skipped due to learnings
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.372Z
Learning: Applies to pacquet/**/tests/**/*.rs : Prefer real fixtures over dependency-injection seams — use `tempfile::TempDir`, the mocked registry, or integration tests spawning the actual binary for happy paths and most error paths; use the DI seam only for filesystem error kinds, deterministic time, shared process-global state, or external-service happy paths

📝 Walkthrough

Walkthrough

This PR refactors the latency proxy to accept configurable listen addresses, adds bandwidth conversion, and integrates optional proxy fronting of the benchmark registry with URL advertisement support. The Verdaccio mock registry is conditionally fronted with latency and bandwidth constraints when configured, with split one-way latency and a computed download cap.

Changes

Benchmark registry latency/bandwidth proxy integration

Layer / File(s) Summary
LatencyProxy refactoring and bandwidth conversion
pacquet/tasks/integrated-benchmark/src/latency_proxy.rs, pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs
LatencyProxy::spawn_on accepts an explicit listen socket address and the existing spawn method now delegates to it with an ephemeral localhost address. New mbps_to_bytes_per_sec(mbps: f64) -> Option<u64> utility converts megabits-per-second to bytes-per-second, returning None for non-finite or non-positive inputs and clamping positive results to a minimum of 1 byte/s. Tests verify exact bind address matching and conversion behavior.
Registry mock public_url configuration
pacquet/tasks/registry-mock/src/pnpr_command.rs, pacquet/tasks/registry-mock/src/mock_instance.rs, pacquet/tasks/registry-mock/src/main.rs
pnpr_command now accepts an optional public_url parameter, trims trailing slashes, and defaults to deriving from port when not provided. MockInstanceOptions adds a public_url field that threads through the spawned pnpr process. AutoMockInstance initializes it to None by default, and registry-mock/main explicitly sets it in launch().
WorkEnv proxy and cache populator support
pacquet/tasks/integrated-benchmark/src/work_env.rs
WorkEnv adds a registry_cache_populator field for the untimed cache-populator benchmark phase, separate from the main client_registry URL. start_registry_proxy now returns None for both npm and verdaccio modes (Verdaccio proxying is now managed in main). registry_for returns the cache-populator URL when selected. Local mbps_to_bytes_per_sec is removed and imported from latency_proxy.
Benchmark main integration of proxy and registry
pacquet/tasks/integrated-benchmark/src/main.rs
When Verdaccio is enabled and bandwidth or latency is configured, a LatencyProxy is spawned to front the registry. The proxy is created with split one-way latency and a computed download bandwidth cap, configured to advertise itself via public_url to clients. The derived registry_cache_populator URL (pointing to the internal upstream port) is passed to WorkEnv, while timed clients connect through the proxy. The proxy is explicitly dropped at shutdown to terminate the process.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • pnpm/pnpm#12237: Both PRs modify pacquet/tasks/integrated-benchmark/src/latency_proxy.rs and related benchmark plumbing around LinkProfile and MBps-to-bytes conversion, implementing the foundational proxy improvements.
  • pnpm/pnpm#12166: The main PR extends LatencyProxy and work_env/main to proxy the registry, which directly overlaps with the retrieved PR's introduction of LatencyProxy for injected latency in benchmarks.

Poem

🐰 A proxy hops through, with bandwidth and delay,
Verdaccio now wears a masquerade's sway,
URLs advertised, cache populating clean,
The registry's latency made visible and keen!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: route benchmark registry tarballs through proxy' directly and concisely describes the main change—ensuring tarball downloads in benchmarks are routed through the latency/bandwidth proxy instead of bypassing it.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/benchmark-registry-public-url-proxy

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.

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.00      7.8±0.18ms   557.0 KB/sec    1.02      7.9±0.50ms   547.3 KB/sec

@zkochan zkochan marked this pull request as ready for review June 7, 2026 10:40
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Review Summary by Qodo

Route benchmark registry tarballs through latency proxy

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Route registry tarball downloads through latency proxy in Verdaccio mode
  - Previously, packuments were fetched through the proxy but tarball URLs bypassed it
  - Now, the proxy binds to the public registry port before Verdaccio starts
  - Verdaccio advertises proxied tarball URLs via configurable --public-url
• Add spawn_on method to LatencyProxy for custom listen addresses
• Extract mbps_to_bytes_per_sec conversion to latency_proxy module
• Separate cache populator registry URL from client registry URL
Diagram
flowchart LR
  A["Verdaccio<br/>upstream port"] -->|"LatencyProxy<br/>spawn_on"| B["Public registry<br/>port"]
  C["Packuments"] -->|"advertise via<br/>public_url"| B
  D["Tarball URLs"] -->|"now routed<br/>through proxy"| B
  B -->|"emulated latency<br/>+ bandwidth"| E["Benchmark clients"]
  F["Cache populator"] -->|"direct URL<br/>registry_cache_populator"| A

Loading

Grey Divider

File Changes

1. pacquet/tasks/integrated-benchmark/src/latency_proxy.rs ✨ Enhancement +23/-2

Add spawn_on method and extract mbps conversion

• Add Ipv4Addr import for address handling
• Refactor spawn to delegate to new spawn_on method
• Add spawn_on method accepting custom listen address
• Extract mbps_to_bytes_per_sec conversion function with documentation
• Add comprehensive unit tests for the conversion function

pacquet/tasks/integrated-benchmark/src/latency_proxy.rs


2. pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs 🧪 Tests +36/-1

Add tests for spawn_on and mbps conversion

• Add test for binding to requested listen address via spawn_on
• Add test for mbps_to_bytes_per_sec conversion edge cases
• Verify proxy correctly forwards traffic through custom address

pacquet/tasks/integrated-benchmark/src/latency_proxy/tests.rs


3. pacquet/tasks/integrated-benchmark/src/main.rs 🐞 Bug fix +46/-2

Spawn registry proxy before Verdaccio with public URL

• Import LatencyProxy, LinkProfile, and mbps_to_bytes_per_sec
• Determine if proxy should wrap Verdaccio based on latency/bandwidth settings
• Calculate separate upstream port for Verdaccio when proxy is needed
• Spawn registry proxy on public port before Verdaccio starts
• Pass public_url to Verdaccio so packuments advertise proxied tarball URLs
• Pass registry_cache_populator URL to WorkEnv for untimed cache priming

pacquet/tasks/integrated-benchmark/src/main.rs


View more (4)
4. pacquet/tasks/integrated-benchmark/src/work_env.rs ✨ Enhancement +17/-28

Separate cache populator URL and move conversion function

• Add registry_cache_populator field for separate cache priming URL
• Update start_registry_proxy to skip Verdaccio mode (now handled in main)
• Update registry_for to use registry_cache_populator for cache populator
• Move mbps_to_bytes_per_sec function to latency_proxy module
• Update comments to reflect new proxy topology

pacquet/tasks/integrated-benchmark/src/work_env.rs


5. pacquet/tasks/registry-mock/src/main.rs ⚙️ Configuration changes +1/-0

Add public_url field to MockInstanceOptions

• Add public_url: None field to MockInstanceOptions in launch function

pacquet/tasks/registry-mock/src/main.rs


6. pacquet/tasks/registry-mock/src/mock_instance.rs ✨ Enhancement +4/-2

Add public_url option to MockInstanceOptions

• Add public_url: Option<&'a str> field to MockInstanceOptions struct
• Pass public_url to pnpr_command when spawning process
• Add public_url: None to RegistryAnchor initialization

pacquet/tasks/registry-mock/src/mock_instance.rs


7. pacquet/tasks/registry-mock/src/pnpr_command.rs ✨ Enhancement +16/-6

Add public_url parameter to pnpr_command

• Add public_url: Option parameter to pnpr_command function
• Implement logic to use provided public_url or default to port_to_url(port)
• Update documentation explaining public_url override for proxy scenarios
• Pass computed public_url to pnpr --public-url argument

pacquet/tasks/registry-mock/src/pnpr_command.rs


Grey Divider

Qodo Logo

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Integrated-Benchmark Report (Linux)

Each scenario has pacquet rows (direct install) and pnpr rows (the same client through the pnpr install accelerator), so pnpr@HEAD vs pacquet@HEAD is the pnpr-vs-direct ratio. Cold-store scenarios wipe the client store between runs (warm server); hot-store scenarios keep it warm. The pacquet@HEAD rows feed the pacquet Bencher testbed; the pnpr@HEAD rows feed the pnpr testbed.

Scenario: Isolated linker: fresh restore, cold cache + cold store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 10.034 ± 0.303 9.874 10.853 1.87 ± 0.06
pacquet@main 9.963 ± 0.085 9.860 10.149 1.85 ± 0.04
pnpr@HEAD 5.479 ± 0.140 5.318 5.762 1.02 ± 0.03
pnpr@main 5.376 ± 0.092 5.324 5.635 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 10.033518900839999,
      "stddev": 0.30345354684016834,
      "median": 9.90727660314,
      "user": 3.0263637599999997,
      "system": 3.2359478399999992,
      "min": 9.87353643564,
      "max": 10.85272034164,
      "times": [
        10.85272034164,
        10.13941414264,
        9.88063856264,
        9.88801182064,
        9.93047722064,
        9.87353643564,
        9.87422967364,
        9.87496302164,
        10.09465640364,
        9.92654138564
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 9.96258733214,
      "stddev": 0.08473714400473184,
      "median": 9.936965892139998,
      "user": 3.09955276,
      "system": 3.2670983399999995,
      "min": 9.85951104364,
      "max": 10.14932624864,
      "times": [
        9.85951104364,
        9.94714717164,
        9.92766049164,
        9.97236176064,
        10.14932624864,
        9.946271292639999,
        9.920740606639999,
        9.92129807564,
        9.91247806464,
        10.06907856564
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 5.4789763462400005,
      "stddev": 0.14026222596409782,
      "median": 5.465871871140001,
      "user": 2.49565276,
      "system": 2.9989997399999995,
      "min": 5.3182271526400005,
      "max": 5.76164018464,
      "times": [
        5.76164018464,
        5.351703205640001,
        5.56444147164,
        5.4350003546400005,
        5.4967433876400005,
        5.3182271526400005,
        5.34936963164,
        5.569501803640001,
        5.572730039640001,
        5.3704062306400004
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 5.376191070140001,
      "stddev": 0.09247396637412517,
      "median": 5.3511288426400005,
      "user": 2.44168646,
      "system": 2.9384521399999994,
      "min": 5.323546754640001,
      "max": 5.63523234164,
      "times": [
        5.32762849764,
        5.34977186664,
        5.323546754640001,
        5.38228321564,
        5.352485818640001,
        5.34193032864,
        5.356595517640001,
        5.33992443264,
        5.35251192764,
        5.63523234164
      ]
    }
  ]
}

Scenario: Isolated linker: fresh restore, hot cache + hot store

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 638.1 ± 10.9 623.9 653.4 1.00
pacquet@main 666.4 ± 62.8 622.7 833.2 1.04 ± 0.10
pnpr@HEAD 763.6 ± 27.2 735.3 815.8 1.20 ± 0.05
pnpr@main 734.5 ± 14.0 718.4 767.1 1.15 ± 0.03
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.63809734274,
      "stddev": 0.010860011714028726,
      "median": 0.6394429452399999,
      "user": 0.35823035999999997,
      "system": 1.3100516,
      "min": 0.62387694424,
      "max": 0.6533907302399999,
      "times": [
        0.63706775424,
        0.62387694424,
        0.64181813624,
        0.63442098524,
        0.65008787324,
        0.64216682624,
        0.6533907302399999,
        0.62520152624,
        0.62496029124,
        0.64798236024
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.66640631074,
      "stddev": 0.06280626967639591,
      "median": 0.64871264724,
      "user": 0.36528666,
      "system": 1.3150287,
      "min": 0.6226835562399999,
      "max": 0.83318258624,
      "times": [
        0.64420817724,
        0.62842033924,
        0.62698857624,
        0.83318258624,
        0.69148354124,
        0.67501500924,
        0.65932387224,
        0.62954033224,
        0.6226835562399999,
        0.65321711724
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.76356158084,
      "stddev": 0.027204866854295715,
      "median": 0.75500958424,
      "user": 0.38342785999999995,
      "system": 1.3110958,
      "min": 0.73525655524,
      "max": 0.81577511524,
      "times": [
        0.74598723724,
        0.78786106324,
        0.77264911224,
        0.76216343124,
        0.74192113024,
        0.81577511524,
        0.74785573724,
        0.73525655524,
        0.78985189224,
        0.73629453424
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.7344630365399999,
      "stddev": 0.013976198376575029,
      "median": 0.7332127452399999,
      "user": 0.36968056,
      "system": 1.3099843999999998,
      "min": 0.71841544224,
      "max": 0.76712277924,
      "times": [
        0.73258201224,
        0.73581030224,
        0.76712277924,
        0.74092142324,
        0.73384347824,
        0.73067648724,
        0.71923235124,
        0.71841544224,
        0.72477112924,
        0.74125496024
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, cold cache + cold store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 9.235 ± 0.055 9.161 9.308 1.82 ± 0.02
pacquet@main 9.203 ± 0.035 9.163 9.287 1.81 ± 0.01
pnpr@HEAD 5.085 ± 0.036 5.038 5.132 1.00
pnpr@main 5.175 ± 0.140 5.056 5.413 1.02 ± 0.03
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 9.234728632579998,
      "stddev": 0.055409361377568606,
      "median": 9.22211971178,
      "user": 3.5702595800000005,
      "system": 3.29330912,
      "min": 9.160590557779999,
      "max": 9.30842817578,
      "times": [
        9.28623361378,
        9.20062954078,
        9.30842817578,
        9.22371408578,
        9.160590557779999,
        9.16724937678,
        9.19636573178,
        9.29573770178,
        9.28781220378,
        9.22052533778
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 9.20338942518,
      "stddev": 0.03466805527144006,
      "median": 9.20099970728,
      "user": 3.5266604799999994,
      "system": 3.2473908199999997,
      "min": 9.162718588779999,
      "max": 9.28672024678,
      "times": [
        9.20743845278,
        9.196508567779999,
        9.28672024678,
        9.22356172978,
        9.162718588779999,
        9.20549084678,
        9.208525351779999,
        9.19075321978,
        9.18187335078,
        9.17030389678
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 5.08489146808,
      "stddev": 0.035571834891795016,
      "median": 5.081262922780001,
      "user": 2.2852764800000003,
      "system": 2.8291888199999997,
      "min": 5.037812333780001,
      "max": 5.13185984778,
      "times": [
        5.12733827078,
        5.092226113780001,
        5.05307645278,
        5.0532104247800005,
        5.095462574780001,
        5.037812333780001,
        5.05768686678,
        5.13185984778,
        5.0702997317800005,
        5.129942063780001
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 5.17523135608,
      "stddev": 0.1402656511525214,
      "median": 5.11176897328,
      "user": 2.27337688,
      "system": 2.7985390199999998,
      "min": 5.055507154780001,
      "max": 5.41291195378,
      "times": [
        5.055507154780001,
        5.06957634178,
        5.38118448578,
        5.25583402478,
        5.060316210780001,
        5.05854816078,
        5.41291195378,
        5.24667542178,
        5.15396160478,
        5.057798201780001
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, hot cache + hot store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 1.374 ± 0.021 1.344 1.401 2.10 ± 0.05
pacquet@main 1.391 ± 0.019 1.363 1.424 2.13 ± 0.05
pnpr@HEAD 0.653 ± 0.013 0.635 0.676 1.00
pnpr@main 0.655 ± 0.010 0.644 0.676 1.00 ± 0.02
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 1.3738334495200002,
      "stddev": 0.020637271340427095,
      "median": 1.3718409774200002,
      "user": 1.53145248,
      "system": 1.7591394599999997,
      "min": 1.3438143119200001,
      "max": 1.40141983592,
      "times": [
        1.35873140692,
        1.3712139869200002,
        1.36365494692,
        1.37246796792,
        1.39853675392,
        1.38208995092,
        1.40141983592,
        1.39719534092,
        1.3438143119200001,
        1.34920999292
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 1.3908001642200003,
      "stddev": 0.018865636949173373,
      "median": 1.38695328642,
      "user": 1.53874248,
      "system": 1.7744262599999998,
      "min": 1.36301177692,
      "max": 1.42407851492,
      "times": [
        1.39550019692,
        1.38441376992,
        1.4199567399200002,
        1.42407851492,
        1.3837181999200001,
        1.39171848292,
        1.3739917539200002,
        1.38211940392,
        1.36301177692,
        1.38949280292
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.65333799542,
      "stddev": 0.012648748475901443,
      "median": 0.65057604242,
      "user": 0.32653487999999997,
      "system": 1.24901216,
      "min": 0.63549212992,
      "max": 0.67570084492,
      "times": [
        0.6481037849200001,
        0.65304829992,
        0.6719622929200001,
        0.67570084492,
        0.65863051892,
        0.6456511289200001,
        0.6554550019200001,
        0.6430740289200001,
        0.6462619229200001,
        0.63549212992
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.65537732792,
      "stddev": 0.009613336237957243,
      "median": 0.6522510554200001,
      "user": 0.32783878000000005,
      "system": 1.25461096,
      "min": 0.6444892899200001,
      "max": 0.6756269329200001,
      "times": [
        0.6525250199200001,
        0.6444892899200001,
        0.6588643349200001,
        0.64868058392,
        0.6470523729200001,
        0.6756269329200001,
        0.6499754859200001,
        0.66631367892,
        0.6519770909200001,
        0.6582684889200001
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, cold cache + hot store

Resolution-only: cold packument cache (full re-resolve over the registry link) with a hot store (no tarball download), so this isolates pnpr offloading the client resolution to its warm server.

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 4.955 ± 0.025 4.925 5.007 7.65 ± 0.09
pacquet@main 4.976 ± 0.035 4.918 5.052 7.68 ± 0.10
pnpr@HEAD 0.648 ± 0.007 0.641 0.662 1.00
pnpr@main 0.685 ± 0.028 0.670 0.763 1.06 ± 0.05
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 4.954607077780001,
      "stddev": 0.024772228472490693,
      "median": 4.9514021459799995,
      "user": 1.7130627600000001,
      "system": 1.8853766,
      "min": 4.92484209898,
      "max": 5.00656098398,
      "times": [
        4.95937352398,
        4.98302396498,
        4.95380724198,
        4.92484209898,
        4.94899704998,
        4.94425827698,
        4.934420969980001,
        5.00656098398,
        4.95937714498,
        4.93140952198
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 4.97583450138,
      "stddev": 0.035068701137444154,
      "median": 4.97434451098,
      "user": 1.7113393599999998,
      "system": 1.9163934,
      "min": 4.91792945198,
      "max": 5.05222552698,
      "times": [
        4.98857811398,
        5.05222552698,
        4.97343253098,
        4.96991076698,
        4.9438388809800005,
        4.99348626198,
        4.91792945198,
        4.984273018980001,
        4.975256490980001,
        4.95941396998
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.64764832628,
      "stddev": 0.006871138548119515,
      "median": 0.64426168048,
      "user": 0.32239676,
      "system": 1.2523397,
      "min": 0.6411507399799999,
      "max": 0.66178590798,
      "times": [
        0.64392515898,
        0.64946053598,
        0.64279764498,
        0.66178590798,
        0.64459820198,
        0.65171418398,
        0.64231048298,
        0.65576907498,
        0.6411507399799999,
        0.64297133098
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.6854683962799999,
      "stddev": 0.02825248952831989,
      "median": 0.67433163398,
      "user": 0.3296168599999999,
      "system": 1.2743820999999997,
      "min": 0.66959122698,
      "max": 0.76344144698,
      "times": [
        0.67586469698,
        0.67271393198,
        0.67965799898,
        0.66959122698,
        0.67247217598,
        0.76344144698,
        0.68775354898,
        0.67089417398,
        0.68949619098,
        0.67279857098
      ]
    }
  ]
}

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12257
Testbedpacquet

🚨 2 Alerts

BenchmarkMeasure
Units
ViewBenchmark Result
(Result Δ%)
Upper Boundary
(Limit %)
isolated-linker.fresh-install.cold-cache.cold-storeLatency
seconds (s)
📈 plot
🚷 threshold
🚨 alert (🔔)
9.23 s
(+216.34%)Baseline: 2.92 s
3.50 s
(263.62%)

isolated-linker.fresh-restore.cold-cache.cold-storeLatency
seconds (s)
📈 plot
🚷 threshold
🚨 alert (🔔)
10.03 s
(+64.63%)Baseline: 6.09 s
7.31 s
(137.20%)

Click to view all benchmark results
BenchmarkLatencyBenchmark Result
milliseconds (ms)
(Result Δ%)
Upper Boundary
milliseconds (ms)
(Limit %)
isolated-linker.fresh-install.cold-cache.cold-store📈 view plot
🚷 view threshold
🚨 view alert (🔔)
9,234.73 ms
(+216.34%)Baseline: 2,919.23 ms
3,503.08 ms
(263.62%)

isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
🚷 view threshold
4,954.61 ms
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
🚷 view threshold
1,373.83 ms
(+3.72%)Baseline: 1,324.56 ms
1,589.48 ms
(86.43%)
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
🚷 view threshold
🚨 view alert (🔔)
10,033.52 ms
(+64.63%)Baseline: 6,094.41 ms
7,313.29 ms
(137.20%)

isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
🚷 view threshold
638.10 ms
(-7.06%)Baseline: 686.58 ms
823.89 ms
(77.45%)
🐰 View full continuous benchmarking report in Bencher

@zkochan zkochan merged commit e42e09d into main Jun 7, 2026
27 of 28 checks passed
@zkochan zkochan deleted the codex/benchmark-registry-public-url-proxy branch June 7, 2026 11:11
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