From b55b8e2f9641a8d3558f9b508dc9da30a04d141b Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Sun, 16 Aug 2026 17:24:50 +0000 Subject: [PATCH] worker: start worker threads from the built-in snapshot Every `new Worker()` runs the whole internal bootstrap (realm, node, web exposure, thread and process-state switches) in its fresh isolate, compiling ~80 builtins with the code cache; only the main thread deserializes its principal context from the built-in snapshot. That bootstrap is about half of a worker's cold start. The bootstrapped principal context in the snapshot is nearly thread-neutral: the worker-side switch scripts (is_not_main_thread, does_not_own_process_state) are written as overrides of the main-thread ones, and the per-thread values of the `worker` binding were the only thread-specific data baked into the context. Let a worker deserialize that same context and EnvSerializeInfo and apply the two worker-side switches on top: - worker binding: threadId, threadName, isMainThread, isInternalThread, ownsProcessState and resourceLimits become lazy properties of the per-isolate template, computed from the Environment on first read. - CreateEnvironment(): when a worker (its IsolateData has a Worker) passes an empty context, deserialize kNodeMainContextIndex and run internal/bootstrap/switches/is_not_main_thread and, unless the worker owns process state, does_not_own_process_state after InitializeMainContext(); skip the isolate error-handler reset. - Worker::Run(): take that path when the built-in (kDefault) snapshot is in use, browser globals are not disabled and --no-worker-snapshot was not given; otherwise bootstrap as before. - is_not_main_thread.js: also delete _debugPause and the profiler idle notifier helpers that is_main_thread.js installs. - --[no-]worker-snapshot per-isolate option, documented. Sequential new Worker() -> 'online' -> terminate goes from ~20.9 ms to ~10.3 ms per worker on x64 Linux; --no-worker-snapshot restores the old number. Signed-off-by: Shelley Vohr --- doc/api/cli.md | 12 ++ doc/node.1 | 6 + .../bootstrap/switches/is_not_main_thread.js | 6 + src/api/environment.cc | 26 ++- src/node_options.cc | 6 + src/node_options.h | 1 + src/node_worker.cc | 149 +++++++++++------- src/node_worker.h | 1 + 8 files changed, 153 insertions(+), 54 deletions(-) diff --git a/doc/api/cli.md b/doc/api/cli.md index fc0a194f8dbd..0440fe2cda98 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -2271,6 +2271,17 @@ added: v6.0.0 Silence all process warnings (including deprecations). +### `--no-worker-snapshot` + + + +> Stability: 1 - Experimental + +Start worker threads by running the internal bootstrap from scratch instead of +deserializing the bootstrapped context from the built-in startup snapshot. + ### `--node-memory-debug`