Pre-instantiate WASM core workers

This commit is contained in:
udo
2026-07-18 01:58:01 +00:00
parent f89e33e241
commit 72fd0dd53a
5 changed files with 103 additions and 219 deletions
+19 -4
View File
@@ -147,8 +147,11 @@ slots, then runs relocations, constructors, and request-pointer binding. This
removes repeated Wasmtime import-type traversal without sharing request state or
changing core-first, unit-load-order symbol resolution.
Each FastCGI child initializes its process-local Wasmtime engine after fork and
before entering the accept loop. This preserves Wasmtime's fork boundary while
preventing the first request assigned to each worker from paying engine startup.
before entering the accept loop. It also creates the linker, resolves the core's
host imports into a store-independent Wasmtime `InstancePre`, and births then
drops one empty workspace. This preserves Wasmtime's fork boundary while
preventing the first request assigned to each worker from paying engine, linker,
or pre-instantiation startup.
Startup duration or failure is written to the service log. The serialized core
module lives in the configured writable cache root rather than beside the
possibly root-owned deployed `core.wasm`; freshness still uses the deployed
@@ -227,7 +230,15 @@ Each request gets a fresh **workspace** — a per-request wasm instance tree wit
the membrane wired in. `wasm_worker_serve(worker, ctx, entry_unit, handler)`
(`src/wasm/worker.cpp`) is the single entry point for *every* mode:
1. Birth a request-scoped workspace with fresh per-request state. Current production workers instantiate a fresh Store, table, core instance, memory, globals, constructors, and request tree for each request. The worker retains only Wasmtime's store-independent host-function definitions and their fixed import order, avoiding reconstruction of 73 identical callback definitions. Every callback resolves the one active request workspace at invocation. Any future snapshot/CoW optimization must preserve that request-isolation contract.
1. Birth a request-scoped workspace with fresh per-request state. Current
production workers create a fresh Store and instantiate the store-independent
`InstancePre`; the resulting core instance owns a fresh exported, growable
function table, memory, globals, constructors, and request tree. The worker
retains only Wasmtime's compiled module, linker, pre-instantiation plan, and
store-independent host-function definitions. Every callback resolves the one
active request workspace at invocation. Legacy cores that import their table
remain supported through the prior per-request import path. Any future
snapshot/CoW optimization must preserve this request-isolation contract.
2. Resolve `entry_unit` + `handler` to an export; components referenced at
runtime are resolved on demand via the `uce_host_component_resolve` hostcall
(`component_resolve()``__uce_<...>` slot), loading dependency modules
@@ -254,7 +265,7 @@ not fork into a private transport type. Validated decode trees move into the
request rather than being deep-copied twice; the historical by-value
`DValue::operator=(DValue)` symbol remains exported so warmed side-module
artifacts stay ABI-compatible. `request_perf()` subdivides birth into policy,
import materialization, core instantiation, export lookup, and initialization,
import materialization, core instantiation, export/table lookup, and initialization,
and context transfer into bytes, host encode, guest allocation/write,
guest decode/application, and free.
@@ -453,6 +464,10 @@ header free-functions are `inline`. The wasm backend exposes only declarations
the generated C++ snapshot has been written. The compiler must either retry
and serve the post-edit source or fail closed; it must never stamp current
source metadata onto wasm produced from an older snapshot.
- **Core compatibility**: the production core owns and exports its growable
function table, enabling `InstancePre`. A separately built legacy
`--import-table` core must still pass the demo and 64-request pool-isolation
groups before the compatibility fallback changes.
`scripts/test_cold_component_deadline.sh` separately compiles a deliberately
cold component that exceeds the development epoch window and proves the
parent request still renders it. The focused shell gates create temporary