Skip to content

perf(cli): read literal config metadata without loading Vite - #2787

Draft
fengmk2 wants to merge 3 commits into
perf/config-resolutionfrom
perf/static-config-metadata
Draft

fengmk2 wants to merge 3 commits into
perf/config-resolutionfrom
perf/static-config-metadata

Conversation

@fengmk2

@fengmk2 fengmk2 commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

The check process initializes Vite even when vite.config.* exports only literal metadata. Read these configs with vp_static_config before calling the JavaScript resolver.

Accept a single export default object with literal lint, fmt, check, run, or staged fields. Imports, config functions, plugin hooks, Vite settings, and executable statements retain runtime resolution. Each call reads the file again so later commands observe changes.

Tool processes still resolve their own configs. The existing benchmark measures static exports and the defineConfig fallback separately.

Single-run comparison with time

Before: 76ce17ced. After: 0afe9b5c9. Each case ran once per version without warmup. Both versions used debug native bindings on Apple M4 Max, macOS 26.2, and Node v22.23.2.

The fixture contains three unformatted TypeScript files in packages/app/src. Config cases use export default { lint: {}, fmt: {} };. Each invocation starts with identical files and an empty NODE_COMPILE_CACHE directory.

The columns show real / user / sys from /usr/bin/time -p, in seconds. The no-config and standalone-tool cases are controls; their variation also shows single-run noise.

Case and CLI arguments Before (s) After (s) Real-time change
Root, no config: check --fix 0.58 / 0.32 / 0.10 0.46 / 0.31 / 0.07 -20.7%
Root, with config: check --fix 0.77 / 0.59 / 0.13 0.69 / 0.52 / 0.13 -10.4%
Root, with config: fmt 0.31 / 0.24 / 0.05 0.31 / 0.24 / 0.05 +0.0%
Root, with config: lint --fix 0.28 / 0.24 / 0.05 0.27 / 0.25 / 0.05 -3.6%
Package, with config: check --fix 0.80 / 0.62 / 0.16 0.64 / 0.50 / 0.11 -20.0%

Example invocation from the fixture root:

NODE_COMPILE_CACHE="$(mktemp -d)" /usr/bin/time -p \
  node "$CHECKOUT/packages/cli/bin/vp" check --fix packages/app/src/*.ts

Set $CHECKOUT to the before or after worktree. Point the fixture's node_modules/vite-plus link to that worktree's packages/cli. Reset the input files before each invocation. Package cases run from packages/app with src/*.ts as the file arguments.

Controlled Linux comparison

CI run compares native revisions 76ce17ced and 0afe9b5c9 on one runner. Both use release bindings, Node v22.18.0, identical JavaScript, and the original CI fixtures.

The following medians use 21 samples per version and case. CPU time is user + sys from /usr/bin/time -p.

Case Elapsed before → after (ms) Change CPU before → after (s)
root/check/minimal 495.6 → 417.8 -15.7% 0.48 → 0.38
root/check/defineConfig 496.2 → 501.8 +1.1% 0.50 → 0.49
package/check/minimal 480.5 → 417.3 -13.2% 0.47 → 0.38
package/check/blocks 495.9 → 429.5 -13.4% 0.49 → 0.39
root/fmt/minimal 171.2 → 172.1 +0.5% 0.15 → 0.15
root/staged/minimal 611.8 → 543.3 -11.2% 0.64 → 0.55

A third CLI snapshot uses the same optimized native binary. Its median differences stay within 1.2%. Each snapshot uses a separate warm compile cache.

Historical measurements from different runners do not isolate the code change. Use the comparison above to assess the second optimization.

Stacked on #2782. Related to #2698.

@fengmk2
fengmk2 added this pull request to stack #2783 September 22, 2026 14:09
@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

CLI artifact sizes (68fe5af)

Final release artifacts built by the canonical build-upstream and build-windows-cli actions.
The dist rows use the Linux build. The core total excludes .node files to match the release artifact.

Artifact Format Base PR Change
packages/cli/dist Directory total 2.12 MiB 2.12 MiB 0 B (0.00%)
packages/core/dist Directory total 3.95 MiB 3.95 MiB 0 B (0.00%)
Combined package dist Directory total 6.07 MiB 6.07 MiB 0 B (0.00%)
vp (Linux x64) Binary 11.28 MiB 11.28 MiB 0 B (0.00%)
vp (Linux x64) gzip -9 4.88 MiB 4.88 MiB 0 B (0.00%)
NAPI (Linux x64) Binary 32.11 MiB 32.13 MiB +16.00 KiB (+0.05%)
NAPI (Linux x64) gzip -9 12.74 MiB 12.74 MiB +4.38 KiB (+0.03%)
vp (macOS ARM64) Binary 8.41 MiB 8.41 MiB 0 B (0.00%)
vp (macOS ARM64) gzip -9 4.26 MiB 4.26 MiB 0 B (0.00%)
NAPI (macOS ARM64) Binary 39.72 MiB 39.72 MiB +16 B (+0.00%)
NAPI (macOS ARM64) gzip -9 17.04 MiB 17.05 MiB +7.02 KiB (+0.04%)
vp (Windows x64) Binary 9.16 MiB 9.16 MiB 0 B (0.00%)
vp (Windows x64) gzip -9 4.00 MiB 4.00 MiB 0 B (0.00%)
NAPI (Windows x64) Binary 27.07 MiB 27.09 MiB +18.00 KiB (+0.06%)
NAPI (Windows x64) gzip -9 10.84 MiB 10.84 MiB +7.33 KiB (+0.07%)
Trampoline (Windows x64) Binary 13.50 KiB 13.50 KiB 0 B (0.00%)
Trampoline (Windows x64) gzip -9 7.09 KiB 7.09 KiB -1 B (-0.01%)
Installer (Windows x64) Binary 4.56 MiB 4.56 MiB 0 B (0.00%)
Installer (Windows x64) gzip -9 2.13 MiB 2.13 MiB 0 B (0.00%)

@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark run for PR head 68fe5afb7c22d2bd6adaee9bbd4762f393ad6f99.

6 case(s) changed by more than ±5% in median time. Negative changes are faster; positive changes are slower.

Config performance

Baseline revision: daef3076e332d6f0074b2484be29cecc612d9b34.

Current revision: 41ce6bd004e01e4d8ab00e132637a298b4a07fa6. Node v22.18.0; linux/x64; AMD EPYC.

Case Median (ms), baseline → current p95 (ms), baseline → current Median change Config evaluations (current, separate probe)
root/check/no-config 223.0 → 252.4 244.0 → 269.6 +29.5 ms (+13.2%) 0
root/check/minimal 472.5 → 485.7 557.1 → 552.5 +13.2 ms (+2.8%) check: 1, oxfmt: 1, oxlint: 1, oxfmt: 1
root/check/defineConfig 479.5 → 569.4 730.7 → 688.5 +89.9 ms (+18.8%) check: 1, oxfmt: 1, oxlint: 1, oxfmt: 1
package/check/minimal 472.7 → 495.3 507.1 → 583.4 +22.6 ms (+4.8%) check: 1, oxfmt: 1, oxlint: 1, oxfmt: 1
package/check/blocks 476.3 → 479.4 537.0 → 540.8 +3.1 ms (+0.7%) check: 1, oxfmt: 1, oxlint: 1, oxfmt: 1
root/fmt/minimal 167.3 → 202.0 195.8 → 222.3 +34.7 ms (+20.7%) oxfmt: 1
root/lint/minimal 138.3 → 163.4 158.4 → 203.4 +25.1 ms (+18.2%) oxlint: 1
root/staged/minimal 609.8 → 660.8 680.2 → 758.8 +50.9 ms (+8.4%) staged: 1, check: 1, oxfmt: 1, oxlint: 1, oxfmt: 1
root/staged/noop 146.3 → 193.6 170.0 → 215.3 +47.3 ms (+32.3%) staged: 1

Fresh processes, warm filesystem and Node compile caches. Config logging is disabled during timing.
A timing regression requires >20% and >40 ms median growth, with current p25 above baseline p75.

  • Regression: root/staged/noop: 146.3 → 193.6 ms (+32.3%)

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://perf-static-config-metadata-viteplus-dev.voidzero-docs.workers.dev (commit 68fe5af)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://7a24ebc5-viteplus-dev.voidzero-docs.workers.dev 68fe5af 2026-09-22T15:11:55.276Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://4f06d2de-viteplus-dev.voidzero-docs.workers.dev 0afe9b5 2026-09-22T14:10:18.844Z Visit the dashboard ↗

@fengmk2

fengmk2 commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

The same-runner comparison confirms that the second optimization reduces config loading time. The earlier cross-run report did not isolate the code change.

Controlled CI run: Linux x64, Node v22.18.0, release native bindings, 21 samples per version and case. The CLI snapshots use identical JavaScript, dependencies, and fixtures. Only the native revision changes from 76ce17ced to 0afe9b5c9.

Case Before → after (ms) Change CPU time before → after (s)
root/check/no-config 222.8 → 221.8 -0.4% 0.12 → 0.12
root/check/minimal 495.6 → 417.8 -15.7% 0.48 → 0.38
root/check/defineConfig 496.2 → 501.8 +1.1% 0.50 → 0.49
package/check/minimal 480.5 → 417.3 -13.2% 0.47 → 0.38
package/check/blocks 495.9 → 429.5 -13.4% 0.49 → 0.39
root/fmt/minimal 171.2 → 172.1 +0.5% 0.15 → 0.15
root/lint/minimal 139.7 → 132.7 -5.0% 0.15 → 0.15
root/staged/minimal 611.8 → 543.3 -11.2% 0.64 → 0.55
root/staged/noop 141.4 → 141.4 +0.0% 0.17 → 0.18

The elapsed-time column shows medians. CPU time is the median of user + sys from /usr/bin/time -p. A third CLI snapshot uses the same optimized binary; its median differences stay within 1.2%. The lint difference is not credited to static config resolution, which it does not use.

The original reports used different runners and compared historical medians. Matching AMD EPYC, CPU count and Node version did not control runner conditions. Unchanged paths became 15–20% slower in the earlier run. A rerun of unchanged product code now becomes 5.8–18.4% faster across the cases. These cross-job changes can hide the optimization.

Both CI source revisions differ only by this optimization. Dependency changes and unrelated merge commits are excluded. The original jobs lack CPU scheduling and frequency telemetry, so the precise host-level cause cannot be recovered. Their cache-hit versus fresh-build difference is not independently proven causal.

The exact-fixture local repeat also improves literal checks by 7.6–10.1%. Local debug and CI release builds explain why their absolute times and percentages differ.

The benchmark should compare base and head within one job, with balanced execution order and separate warm compile caches. Keep ±5% comments based on those measurements; use historical artifacts for trends. The temporary diagnostic instrumentation will be removed from the product PR.

This branch has not been deployed

No deployments
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