Skip to content

perf(cli): reduce release binary size and compare preview artifacts - #3086

Open
fengmk2 wants to merge 9 commits into
mainfrom
perf/binary-size-analysis
Open

fengmk2 wants to merge 9 commits into
mainfrom
perf/binary-size-analysis

Conversation

@fengmk2

@fengmk2 fengmk2 commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

This change reduces the standalone vp executable size with a step-local CARGO_PROFILE_RELEASE_OPT_LEVEL=z override. Fat LTO remains enabled for both the standalone executable and the NAPI addon. The addon contains Rolldown and Oxc and keeps its existing release settings.

Artifact Base PR
Standalone vp executable opt-level=3, lto="fat" opt-level="z", lto="fat"
NAPI addon, including Rolldown and Oxc opt-level=3, lto="fat" opt-level=3, lto="fat"

On Apple M4 Max with macOS ARM64, the executable decreases from 7,991,312 to 4,954,496 bytes (38.0% smaller). The table compares standalone CLI commands from the same source commit, a4e9c5932, with fat LTO in both builds. These CLI timings do not measure bundling. A separate vp build comparison below measures the bundled Rolldown.

Workload opt-level=3 opt-level="z" Slowdown
vp -V, no local installation 4.287 ms 4.337 ms 1.1%
vp -V, local package and toolchain manifest 4.322 ms 4.387 ms 1.5%
vp env current node --json 4.35 ms 4.50 ms 3.4%
Same command, 20 directories below the project root 4.95 ms 5.13 ms 3.6%
vp node -e '' 32.96 ms 33.06 ms 0.3%
vp env exec npm --version 70.23 ms 70.22 ms No consistent difference
vp env install 22.13.1, runtime absent 1,068 ms 1,127 ms 5.5%

The version command adds 0.05–0.07 ms. Its measurements use 360 runs per binary per workload, in three rounds with randomized execution order. Environment commands add about 0.1–0.2 ms. Fresh Node.js installation adds 59 ms.

These measurements use warm filesystem caches. Installation uses a local mirror and includes signature verification, checksum verification, and extraction. Linux and Windows performance remains unmeasured. The performance report contains details for the environment and installation workloads.

The vp build comparison uses the same native addon, Node.js 22.23.2, Vite 8.3.4, and Rolldown 1.2.14 for both variants. Fat LTO stays enabled. Each workload has 60 runs per variant in three rounds with balanced, randomized execution order.

vp build workload Standalone opt-level=3 Standalone opt-level="z" Change
threejs10x, 3,693 modules 525.0 ms 528.2 ms +0.6%
Same input, minification and source maps 660.9 ms 665.5 ms +0.7%
2,000 TypeScript modules, 20 dynamic chunks, minification and source maps 401.9 ms 401.4 ms -0.1%

These workloads show no consistent slowdown. Differences change sign across rounds, and all 95% confidence intervals include zero. Timings include CLI startup, bundling, and output writes, with warm filesystem caches and no task cache. The Rolldown report includes the runner and raw measurements. These results do not measure disabling fat LTO or changing the NAPI optimization level.

For comparison, the main Rust CLIs in uv and pnpm retain opt-level=3. Both use lto="fat", codegen-units=1, symbol stripping, no debug information, and panic="abort". uv uses opt-level="z" for its separate uv-build binary.

uv's release workflow also uses profile-guided optimization on selected targets. Its macOS builds use LLD to merge identical code. pnpm's release workflow sets -C force-unwind-tables=no for the Linux CLI. Its NAPI addon keeps unwind tables and uses panic="unwind".

The preview workflow adds a PR comment that compares each binary with the latest stable release. It shows raw sizes, gzip sizes, and changes for all eight targets, including Windows installers and trampolines.

The report uses code from the default branch and reads preview binaries without executing them. It updates the existing comment only while the PR still points to the built commit.

The Linux report uses the npmx unpacked-size metric in decimal MB. It sums package payload bytes and registry dist.unpackedSize for production and optional dependencies on linux-x64-glibc. Each package name contributes once. The resolver follows npm: aliases, including @voidzero-dev/vite-plus-core.

The CLI payload is 2.8 MB. Base and PR both total 126.1 MB with 79 dependencies in the Linux CI report. npmx currently reports 109.5 MB and 67 dependencies. Its resolver omits the core package and 11 dependencies. This report includes them.

The analysis and separate prototype patches in bench/binary-size/ cover the remaining work toward the 50% target for each binary.

@fengmk2
fengmk2 force-pushed the perf/binary-size-analysis branch from a5def7e to 5156822 Compare October 16, 2026 13:26
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://perf-binary-size-analysis-viteplus-dev.voidzero-docs.workers.dev (commit 554d5cd)

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://3f9a49c4-viteplus-dev.voidzero-docs.workers.dev 554d5cd 2026-10-17T06:17:12.473Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://90e1de5f-viteplus-dev.voidzero-docs.workers.dev f8dd9f8 2026-10-17T03:53:48.217Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://9b18bb57-viteplus-dev.voidzero-docs.workers.dev 26acf72 2026-10-17T03:43:11.283Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://855adbd1-viteplus-dev.voidzero-docs.workers.dev 4ee2e4e 2026-10-17T03:41:32.988Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://3cdc0760-viteplus-dev.voidzero-docs.workers.dev 632c053 2026-10-17T03:20:08.054Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://3d86c807-viteplus-dev.voidzero-docs.workers.dev 4decafa 2026-10-16T14:43:42.424Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://fc22a39e-viteplus-dev.voidzero-docs.workers.dev edeb872 2026-10-16T14:01:32.630Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://ccf598c4-viteplus-dev.voidzero-docs.workers.dev a4e9c59 2026-10-16T13:29:28.065Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://80de8d5f-viteplus-dev.voidzero-docs.workers.dev 5156822 2026-10-16T13:27:29.338Z Visit the dashboard ↗

@fengmk2 fengmk2 added the preview-build Publish this PR's commits to the registry bridge as preview builds label Oct 16, 2026
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

CLI artifact sizes (554d5cd)

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.
The CLI total uses the npmx unpacked-size metric: package payload bytes plus registry dist.unpackedSize for dependencies, in decimal MB.
It resolves production and optional dependencies for Linux x64 glibc, counts each package name once, and follows npm aliases so the bundled core is included. Dependency counts exclude the CLI itself.
It excludes development and peer dependencies, filesystem allocation, install-time files, the standalone vp executable, Node.js, and package-manager caches.

Artifact Format Base PR Change
CLI including dependencies (Linux x64 glibc) Total unpacked 126.1 MB (79 deps) 126.1 MB (79 deps) 0 B (0.00%)
packages/cli/dist Directory total 2.20 MiB 2.20 MiB 0 B (0.00%)
packages/core/dist Directory total 4.08 MiB 4.08 MiB 0 B (0.00%)
Combined package dist Directory total 6.28 MiB 6.28 MiB 0 B (0.00%)
vp (Linux x64) Binary 10.21 MiB 7.13 MiB -3.08 MiB (-30.18%)
vp (Linux x64) gzip -9 4.50 MiB 3.32 MiB -1.19 MiB (-26.34%)
NAPI (Linux x64) Binary 34.53 MiB 34.53 MiB 0 B (0.00%)
NAPI (Linux x64) gzip -9 13.81 MiB 13.81 MiB 0 B (0.00%)
vp (macOS ARM64) Binary 7.62 MiB 4.72 MiB -2.90 MiB (-38.00%)
vp (macOS ARM64) gzip -9 3.94 MiB 2.84 MiB -1.10 MiB (-27.99%)
NAPI (macOS ARM64) Binary 41.52 MiB 41.52 MiB 0 B (0.00%)
NAPI (macOS ARM64) gzip -9 17.97 MiB 17.97 MiB 0 B (0.00%)
vp (Windows x64) Binary 8.29 MiB 5.18 MiB -3.10 MiB (-37.42%)
vp (Windows x64) gzip -9 3.66 MiB 2.43 MiB -1.23 MiB (-33.53%)
NAPI (Windows x64) Binary 30.60 MiB 30.60 MiB 0 B (0.00%)
NAPI (Windows x64) gzip -9 12.51 MiB 12.51 MiB 0 B (0.00%)
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 0 B (0.00%)
Installer (Windows x64) Binary 3.63 MiB 3.63 MiB -1.00 KiB (-0.03%)
Installer (Windows x64) gzip -9 1.78 MiB 1.78 MiB -178 B (-0.01%)

@github-actions

Copy link
Copy Markdown
Contributor

Registry bridge build (a4e9c59)

This commit build is published to the registry bridge, which serves these as ordinary npm versions (every other package proxies to npmjs):

Package Version
vite-plus 0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0
@voidzero-dev/vite-plus-core 0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0
create-vite-plus 0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0

Install the Vite+ CLI built from this commit, then migrate a project:

# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/voidzero-dev/vite-plus/a4e9c5932e069b5aea5b9c0136222ddada73bed0/packages/cli/install.sh | VP_PR_VERSION=3086 VP_LEGACY_INSTALLER_URL=https://raw.githubusercontent.com/voidzero-dev/vite-plus/a4e9c5932e069b5aea5b9c0136222ddada73bed0/packages/cli/install-legacy.sh bash
# Windows (PowerShell)
$env:VP_PR_VERSION="3086"; $env:VP_LEGACY_INSTALLER_URL="https://raw.githubusercontent.com/voidzero-dev/vite-plus/a4e9c5932e069b5aea5b9c0136222ddada73bed0/packages/cli/install-legacy.ps1"; irm https://raw.githubusercontent.com/voidzero-dev/vite-plus/a4e9c5932e069b5aea5b9c0136222ddada73bed0/packages/cli/install.ps1 | iex

Or download the standalone Windows installer built from this commit:

Architecture Installer
x64 vp-setup-x86_64-pc-windows-msvc.exe
Arm64 vp-setup-aarch64-pc-windows-msvc.exe

GitHub requires you to sign in and downloads each installer as a ZIP artifact. Extract vp-setup.exe, then run it against this preview build:

.\vp-setup.exe --version "0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0" --registry "https://registry-bridge.viteplus.dev/"

After installing, upgrade the current project's vite-plus to this test build with:

vp migrate

Or create a new project from this commit without installing the CLI:

export npm_config_registry=https://registry-bridge.viteplus.dev/ pnpm_config_registry=https://registry-bridge.viteplus.dev/
pnpm create vite-plus@0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0 # or: npm create vite-plus@0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0
$env:npm_config_registry="https://registry-bridge.viteplus.dev/"; $env:pnpm_config_registry="https://registry-bridge.viteplus.dev/"
pnpm create vite-plus@0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0 # or: npm create vite-plus@0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0

pnpm 11+ reads pnpm_config_registry, npm and older pnpm read npm_config_registry. The new project pins this build, so keep the registry set for later installs, or configure it as below.

Or point your package manager at the bridge registry https://registry-bridge.viteplus.dev/:

Package manager Registry config
npm / pnpm / Bun .npmrc: registry=https://registry-bridge.viteplus.dev/
Yarn (v2+) .yarnrc.yml: npmRegistryServer: "https://registry-bridge.viteplus.dev/"

Then pin the build (vite aliases to vite-plus-core; pnpm can use a catalog, npm an overrides entry):

{
  "devDependencies": {
    "vite-plus": "0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0",
    "vite": "npm:@voidzero-dev/vite-plus-core@0.0.0-commit.a4e9c5932e069b5aea5b9c0136222ddada73bed0"
  }
}

@github-actions

Copy link
Copy Markdown
Contributor

🐳 Docker preview image

Built from this PR's registry bridge build:

Image Compressed size
ghcr.io/voidzero-dev/vite-plus:pr-3086 225MB
# remove any stale local copy from a previous run, then pull fresh
docker rmi ghcr.io/voidzero-dev/vite-plus:pr-3086 2>/dev/null; docker pull ghcr.io/voidzero-dev/vite-plus:pr-3086

Quick check:

docker run --rm ghcr.io/voidzero-dev/vite-plus:pr-3086 vp --version

See docs/guide/docker.md for usage.

@fengmk2 fengmk2 added test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: create-e2e Run `vp create` e2e tests test: sfw labels Oct 17, 2026
@fengmk2 fengmk2 self-assigned this Oct 17, 2026
@fengmk2
fengmk2 marked this pull request as ready for review October 17, 2026 03:06
@fengmk2
fengmk2 requested a review from Brooooooklyn October 17, 2026 03:06
@fengmk2
fengmk2 marked this pull request as draft October 17, 2026 03:21
@fengmk2
fengmk2 marked this pull request as ready for review October 17, 2026 03:39

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

preview-build Publish this PR's commits to the registry bridge as preview builds test: create-e2e Run `vp create` e2e tests test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: sfw

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant