Skip to content

chore(build): spawn watcher tools directly instead of via npx#41034

Open
Skn0tt wants to merge 1 commit into
microsoft:mainfrom
Skn0tt:reduce-watch-memory
Open

chore(build): spawn watcher tools directly instead of via npx#41034
Skn0tt wants to merge 1 commit into
microsoft:mainfrom
Skn0tt:reduce-watch-memory

Conversation

@Skn0tt
Copy link
Copy Markdown
Member

@Skn0tt Skn0tt commented May 28, 2026

Summary

Small cleanup. The watch script spawns 8 long-running tools (7 vite watchers + 1 tsc) through npx, which forks an extra sh -c + npm exec wrapper process per tool just to launch another Node.js process. Resolving the bin paths up-front lets us spawn(node, [bin, ...], { shell: false }) directly.

Behaviorally identical (same args reach vite/tsc); also drops the quotePath helper that only existed to escape tsc -p for the shell.

Impact

Removes 8 wrapper processes per watch. Their memory cost varies wildly by OS: ~5 MB ps-RSS each on macOS (heavily compressed for long-running watches; ~36 MB physical footprint per vmmap) up to ~78 MB ps-RSS each on Linux. So somewhere between ~40 MB and ~550 MB freed per watch depending on the platform — modest relative to the watch's total footprint (dominated by tsc -w and the vite workers), but free.

@Skn0tt Skn0tt changed the title chore(build): spawn watcher tools directly instead of via npx chore(build): spawn watcher tools directly instead of via npx (−35% procs, −28% RAM) May 28, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@pavelfeldman
Copy link
Copy Markdown
Member

Process RSS
tsc -w (playwright) 1.28 GB ← biggest
5× vite watch (node) 435 + 291 + 209 + 203 + 178 MB ≈ 1.28 GB
vite sw.config builds (node ×2) 145 + 110 MB ≈ 255 MB
esbuild service 245 MB
npm exec shims ~545 MB (7 × ~78 MB)
build.js parent 122 MB
Total ~3.75 GB

Are you sure we care about npx wrappers?

The watch script orchestrates 7 vite watchers + 1 tsc, each spawned via
`spawn('npx', [...], { shell: true })`. That produces an extra
`sh -c 'npx <tool>'` + `npm exec` wrapper per tool, just to launch
another Node.js process.

Resolve the bin path via `<pkg>/package.json` and spawn `node <bin>`
directly with `shell: false`.

Per `npm run watch` (measured on macOS, fresh start, steady state):
- Processes: 26 → 17 (−9)
- ps RSS sum: 181 MB → 130 MB (−51 MB)
- Per wrapper `vmmap` physical_footprint: ~36 MB (8 wrappers × 36 MB
  ≈ ~290 MB of attributable memory eliminated; most was sitting in the
  macOS compressor for long-running watches)

Behaviorally identical: same args reach vite/tsc.
@Skn0tt Skn0tt force-pushed the reduce-watch-memory branch from d441b87 to 0888d71 Compare May 29, 2026 07:54
@Skn0tt Skn0tt changed the title chore(build): spawn watcher tools directly instead of via npx (−35% procs, −28% RAM) chore(build): spawn watcher tools directly instead of via npx May 29, 2026
@Skn0tt
Copy link
Copy Markdown
Member Author

Skn0tt commented May 29, 2026

Looks like my Copilot only gave me a slice of the real picture ;D I think we should take 545mb when we can get it for free.

I tried replacing tsc with tsgo, but it only helps speed and not memory.

#41047 has some consolidation on the Vite processes - maybe we can get it down to just one.

@github-actions
Copy link
Copy Markdown
Contributor

Test results for "MCP"

1 failed
❌ [chromium] › mcp/cli-keyboard.spec.ts:19 › press @mcp-windows-latest-chromium

7206 passed, 1113 skipped


Merge workflow run.

@github-actions
Copy link
Copy Markdown
Contributor

Test results for "tests 1"

2 flaky ⚠️ [chromium-library] › library/video.spec.ts:647 › screencast › should capture full viewport `@chromium-ubuntu-22.04-node20`
⚠️ [chromium-page] › page/page-request-continue.spec.ts:756 › propagate headers cross origin redirect after interception `@chromium-ubuntu-22.04-node22`

43984 passed, 864 skipped


Merge workflow run.

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.

2 participants