perf: cache the compiled core module so fresh workers deserialize, not recompile

Workers recycle every 8 requests (calls_until_termination=8). Each fresh worker
ran wasmtime::Module::compile() on the 6.8MB bin/wasm/core.wasm — a ~1.3s
Cranelift JIT — on its first request, so every ~8th request spiked to ~1.3s and
dominated suite wall-clock.

Cache the compiled artifact: on worker core-module load, if bin/wasm/core.cwasm
exists and is newer than core.wasm, load it via Module::deserialize_file() (mmap,
~ms); otherwise Module::compile() as before and atomically (temp+rename) write
the serialized artifact for the next worker. Deserialize failure / stale cache
falls back to a normal compile, so it is self-healing; rebuilding core.wasm
(newer mtime) invalidates the cache. Engine config (epoch_interruption,
signals_based_traps(false)) is unchanged, which the serialized format requires.

Implemented via the pi agent (delegated to a gpt-5.3-codex-spark sub-model).
Independently verified on the host: worker-startup request latency drops from
~1.3s to ~23ms (warm 12x /demo/hello.uce: all <=0.023s, no spikes); full suite
wall-clock ~40s -> 20.5s; run_cli_tests --include-wasm-kill => 87 passed, 0
failed, 0 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
root 2026-06-15 00:02:22 +00:00
parent bfd6d33829
commit 560290ca1d

View File

@ -32,6 +32,7 @@
#include <ctime>
#include <fstream>
#include <map>
#include <cstdio>
#include <memory>
#include <optional>
#include <string>
@ -247,10 +248,54 @@ public:
String parse_error;
if(!wasm_parse_sections(bytes, core_dylink, abi_ignored, parse_error))
return("core module: " + parse_error);
String core_cached_path = cfg.core_wasm_path;
if(core_cached_path.size() >= 5 && core_cached_path.rfind(".wasm", core_cached_path.size() - 5) == core_cached_path.size() - 5)
core_cached_path = core_cached_path.substr(0, core_cached_path.size() - 5) + ".cwasm";
else
core_cached_path += ".cwasm";
struct stat core_stat;
struct stat cached_stat;
if(stat(core_cached_path.c_str(), &cached_stat) == 0 && stat(cfg.core_wasm_path.c_str(), &core_stat) == 0)
{
if(cached_stat.st_mtime > core_stat.st_mtime)
{
auto deserialized = wasmtime::Module::deserialize_file(engine, core_cached_path);
if(deserialized)
{
core_module.emplace(deserialized.ok());
return("");
}
}
}
auto compiled = wasmtime::Module::compile(engine, bytes);
if(!compiled)
return("core module compile failed: " + String(compiled.err().message()));
core_module.emplace(compiled.ok());
auto serialized = core_module->serialize();
if(serialized)
{
String tmp = core_cached_path + "." + std::to_string((long long)getpid()) + ".tmp";
auto data = serialized.ok();
{
std::ofstream out(tmp, std::ios::binary | std::ios::trunc);
if(out)
{
out.write((const char*)data.data(), (std::streamsize)data.size());
if(out)
{
out.flush();
out.close();
if(std::rename(tmp.c_str(), core_cached_path.c_str()) != 0)
(void)std::remove(tmp.c_str());
}
}
else
(void)std::remove(tmp.c_str());
}
}
return("");
}