perf(trampoline): raw Win32 rewrite shrinks vp-shim to 8KB - #2466
Draft
fengmk2 wants to merge 3 commits into
Draft
perf(trampoline): raw Win32 rewrite shrinks vp-shim to 8KB#2466fengmk2 wants to merge 3 commits into
fengmk2 wants to merge 3 commits into
Conversation
Move crates/vp_trampoline out of the workspace: cargo ignores `panic` in per-package profile overrides, so the crate needs its own release profile with panic = "immediate-abort". A crate-local .cargo/config.toml enables build-std, which recompiles std under the size profile and compiles out the panic formatting, unwinding, and backtrace machinery. The source is unchanged. vp-shim.exe: 212,992 B to 73,728 B on x86_64-pc-windows-msvc, 190,976 B to 71,168 B on aarch64-pc-windows-msvc. The crate config keeps artifacts in the repo-root target/ directory, so CI steps, the snapshot runner, and install-global-cli find vp-shim.exe in the same place as before. Every former `cargo build -p vp_trampoline` call site now builds from the crate directory so the config applies. rust-toolchain.toml adds the rust-src component (build-std needs the std sources). The root Cargo.lock drops the stale vp_trampoline entry, which --locked commands require. The trampoline RFC records the measured variant table down to a 7KB raw-Win32 recipe for future size work.
…to 8KB On top of the build-std profile, replace the Windows implementation: #![no_main] with a mainCRTStartup entry point (no CRT startup, no std runtime init) and raw KERNEL32 calls instead of std::process::Command, in the uv-trampoline structure. The child command line is the raw GetCommandLineW tail after the program argument, forwarded byte for byte, so the caller's quoting survives exactly. When the parent redirects stdio, the std handles are forced inheritable before CreateProcessW, the same way uv-trampoline and distlib's launcher do. Unlike the previous silent process::exit(1) paths, every failure now reports the failed call, the path involved, and the GetLastError code to stderr; a missing vp.exe additionally prints a recovery hint. vp-shim.exe: 73,728 B to 8,192 B on x86_64-pc-windows-msvc, 71,168 B to 9,216 B on aarch64-pc-windows-msvc. The exe imports only KERNEL32. The non-Windows build keeps the portable std::process::Command implementation so the crate builds and tests everywhere; Unix shims are symlinks and never use it. The pure UTF-16 helpers (program-argument skip, file stem, decimal formatter) live in cmdline.rs with unit tests that run on every platform. The RFC records the raw design, the measured size ladder, and the no_main link gotchas.
✅ Deploy Preview for viteplus-preview canceled.
|
The Build Windows tests archive step enumerates crates/*/ and passed -p vp_trampoline, which is no longer a workspace member; skip it like the justfile test recipe does (its only test module is unix-only, so it has nothing to contribute to the Windows archive). Also apply oxfmt 0.63.0 to the RFC tables, which vp check flags on the CLI E2E jobs.
Contributor
Native binary sizes (
|
| Artifact | Format | Base | PR | Change |
|---|---|---|---|---|
vp (Linux x64) |
Binary | 10.67 MiB | 10.68 MiB | +4.00 KiB (+0.04%) |
vp (Linux x64) |
gzip -9 | 4.62 MiB | 4.62 MiB | +566 B (+0.01%) |
| NAPI (Linux x64) | Binary | 32.02 MiB | 32.03 MiB | +8.00 KiB (+0.02%) |
| NAPI (Linux x64) | gzip -9 | 12.61 MiB | 12.61 MiB | -476 B (-0.00%) |
vp (macOS ARM64) |
Binary | 7.98 MiB | 7.98 MiB | +16 B (+0.00%) |
vp (macOS ARM64) |
gzip -9 | 4.03 MiB | 4.03 MiB | +312 B (+0.01%) |
| NAPI (macOS ARM64) | Binary | 39.68 MiB | 39.68 MiB | +32 B (+0.00%) |
| NAPI (macOS ARM64) | gzip -9 | 16.92 MiB | 16.92 MiB | +893 B (+0.01%) |
vp (Windows x64) |
Binary | 8.55 MiB | 8.56 MiB | +7.00 KiB (+0.08%) |
vp (Windows x64) |
gzip -9 | 3.73 MiB | 3.73 MiB | +1.87 KiB (+0.05%) |
| NAPI (Windows x64) | Binary | 26.89 MiB | 26.90 MiB | +8.50 KiB (+0.03%) |
| NAPI (Windows x64) | gzip -9 | 10.68 MiB | 10.69 MiB | +1.81 KiB (+0.02%) |
| Trampoline (Windows x64) | Binary | 205.00 KiB | 8.00 KiB | -197.00 KiB (-96.10%) |
| Trampoline (Windows x64) | gzip -9 | 99.00 KiB | 3.46 KiB | -95.54 KiB (-96.51%) |
| Installer (Windows x64) | Binary | 4.47 MiB | 4.47 MiB | +5.50 KiB (+0.12%) |
| Installer (Windows x64) | gzip -9 | 2.09 MiB | 2.09 MiB | +1.48 KiB (+0.07%) |
Contributor
Registry bridge build (
|
| Package | Version |
|---|---|
vite-plus |
0.0.0-commit.8a5b4369463a2dff1b6a1cb84b78e4e14297e291 |
@voidzero-dev/vite-plus-core |
0.0.0-commit.8a5b4369463a2dff1b6a1cb84b78e4e14297e291 |
Install the Vite+ CLI built from this commit, then migrate a project:
# macOS / Linux
curl -fsSL https://vite.plus | VP_PR_VERSION=2466 bash# Windows (PowerShell)
$env:VP_PR_VERSION="2466"; irm https://vite.plus/ps1 | iexAfter installing, upgrade the current project's vite-plus to this test build with:
vp migrateOr 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.8a5b4369463a2dff1b6a1cb84b78e4e14297e291",
"vite": "npm:@voidzero-dev/vite-plus-core@0.0.0-commit.8a5b4369463a2dff1b6a1cb84b78e4e14297e291"
}
}
Contributor
🐳 Docker preview imageBuilt from this PR's registry bridge build:
# remove any stale local copy from a previous run, then pull fresh
docker rmi ghcr.io/voidzero-dev/vite-plus:pr-2466 2>/dev/null; docker pull ghcr.io/voidzero-dev/vite-plus:pr-2466Quick check: docker run --rm ghcr.io/voidzero-dev/vite-plus:pr-2466 vp --versionSee docs/guide/docker.md for usage. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Alternative to #2465 for comparison: same build-std plumbing (first commit is the same change), plus a raw Win32 rewrite of the Windows shim on top.
vp-shim.exegoes from 213KB to 8KB.The rewrite follows the uv-trampoline structure:
#![no_main]with amainCRTStartupentry point: no CRT startup, nostdruntime init. Requires theatexitstub described in the RFC (current nightlies register TLS cleanup through Catexit, which otherwise drags CRT startup into the link).std::process::Command. The child command line is the rawGetCommandLineWtail after the program argument, forwarded byte for byte, so the caller's quoting survives exactly. When the parent redirects stdio, the std handles are forced inheritable beforeCreateProcessW(same as uv-trampoline and distlib's launcher).GetLastErrorcode; a missingvp.exealso prints a recovery hint (reinstall orvp env setup). Nocore::fmtanywhere; diagnostics go throughWriteFilewith a hand-rolled decimal formatter.std::process::Commandimplementation (Unix shims are symlinks and never use it). The pure UTF-16 helpers live incmdline.rswith unit tests that run on every platform.Measured with cargo-xwin:
For reference: uv-trampoline ships 45KB (it also carries PE resources, path canonicalization, and job objects), Scoop's default C shim is 136KB. The exe here imports only KERNEL32.
Error reporting compared with #2465
The #2465 source keeps the old code, which avoids
core::fmtby discarding everyio::Errorand exiting bare, so it cannot print a reason. This PR printsGetLastErrorcodes through a hand-rolled decimal formatter, at a cost of about 1.5KB:exit(1), no output at allvp.exemissing (broken install, deletedcurrentjunction, upgrade race)vite-plus: failed to execute <path>, no reason givenvp.exe is missing; reinstall vite-plus or run vp env setupvp.exepresent but not runnable (access denied, corrupt binary)VP_HOME/VP_SHIM_TOOLCommand::status)panic = "immediate-abort"in both)Verified locally: release builds for both Windows targets and the host, 8 unit tests, crate clippy/fmt (in-crate and via
--manifest-pathfrom the root), andcargo metadata --lockedon the workspace. The Windows implementation is new code, so the Windows CI leg (PTY snapshot suite,env_install_*and corepack shim fixtures) is the behavior gate that matters before either PR lands.