Precompile native modules off request path

This commit is contained in:
udo
2026-07-16 22:51:16 +00:00
parent a247c2b520
commit 8dd307d316
6 changed files with 84 additions and 8 deletions
+19 -7
View File
@@ -1266,7 +1266,8 @@ void run_proactive_compiler()
bool source_missing = false;
auto retry_it = retry_after.find(file_name);
bool retry_allowed = (retry_it == retry_after.end() || time_precise() >= retry_it->second);
if(compiler_unit_needs_recompile(&background_context, file_name, &source_missing) && retry_allowed)
bool needs_compile = compiler_unit_needs_recompile(&background_context, file_name, &source_missing);
if(needs_compile && retry_allowed)
proactive_compile_queue_push(compile_queue, file_name);
if(source_missing)
{
@@ -1291,14 +1292,15 @@ void run_proactive_compiler()
auto retry_it = retry_after.find(file_name);
if(retry_it != retry_after.end() && time_precise() < retry_it->second)
continue;
bool failed = false;
String wasm_path = server_state.config["BIN_DIRECTORY"] + file_name + ".wasm";
if(compiler_unit_needs_recompile(&background_context, file_name, &source_missing))
{
printf("(i) proactive compile %s\n", file_name.c_str());
auto su = get_shared_unit(&background_context, file_name);
if(su && su->compiler_messages == "")
retry_after.erase(file_name);
else
retry_after[file_name] = time_precise() + failure_retry_interval;
failed = !su || su->compiler_messages != "";
if(su)
wasm_path = su->wasm_name;
}
else if(source_missing)
{
@@ -1306,10 +1308,20 @@ void run_proactive_compiler()
compiler_untrack_known_unit(&background_context, file_name);
retry_after.erase(file_name);
}
else
if(!source_missing && !failed && wasm_serialized_module_needs_refresh(wasm_path))
{
retry_after.erase(file_name);
printf("(i) proactive serialize %s\n", file_name.c_str());
String serialize_error = wasm_serialize_module_artifact(wasm_path);
if(serialize_error != "")
{
printf("(!) proactive serialize failed for %s: %s\n", file_name.c_str(), serialize_error.c_str());
failed = true;
}
}
if(!source_missing && failed)
retry_after[file_name] = time_precise() + failure_retry_interval;
else if(!source_missing)
retry_after.erase(file_name);
background_context.session.clear();
background_context.session_loaded_hash = "";
clear_shared_unit_cache(server_state);
+10
View File
@@ -93,6 +93,16 @@ String wasm_backend_start(Request& request)
return(wasm_backend_ensure_started(&request));
}
bool wasm_serialized_module_needs_refresh(const String& wasm_path)
{
return(WasmWorker::serialized_module_needs_refresh(wasm_path));
}
String wasm_serialize_module_artifact(const String& wasm_path)
{
return(WasmWorker::serialize_module_artifact(wasm_path));
}
static bool wasm_artifact_exists(Request* context, const String& entry_unit)
{
if(entry_unit == "")
+5
View File
@@ -14,6 +14,11 @@ bool wasm_backend_should_handle(Request& request, const String& entry_unit);
// requests. Returns "" on success or the retained backend initialization error.
String wasm_backend_start(Request& request);
// Proactive compiler hooks for keeping Wasmtime's native serialization newer
// than a compiled unit artifact before any request worker loads it.
bool wasm_serialized_module_needs_refresh(const String& wasm_path);
String wasm_serialize_module_artifact(const String& wasm_path);
// Serve a request through a wasm workspace by invoking a named unit handler —
// "render", "cli", "websocket", "serve_http", "serve_http:named" — and populate
// the native Request. Returns "" on success or a collapsed error. The handler is
+30
View File
@@ -1049,6 +1049,36 @@ public:
return(unit);
}
static bool serialized_module_needs_refresh(const String& wasm_path)
{
struct stat wasm_stat;
struct stat cached_stat;
String cached_path = cached_wasm_path(wasm_path);
if(stat(wasm_path.c_str(), &wasm_stat) != 0)
return(false);
if(stat(cached_path.c_str(), &cached_stat) != 0)
return(true);
return(cached_stat.st_mtim.tv_sec < wasm_stat.st_mtim.tv_sec ||
(cached_stat.st_mtim.tv_sec == wasm_stat.st_mtim.tv_sec && cached_stat.st_mtim.tv_nsec <= wasm_stat.st_mtim.tv_nsec));
}
static String serialize_module_artifact(const String& wasm_path)
{
if(!serialized_module_needs_refresh(wasm_path))
return("");
std::vector<u8> bytes;
if(!wasm_read_file(wasm_path, bytes))
return("cannot read " + wasm_path);
wasmtime::Engine engine = make_engine();
String error;
auto module = compile_and_cache_module(engine, cached_wasm_path(wasm_path), bytes, error);
if(!module)
return(error);
if(serialized_module_needs_refresh(wasm_path))
return("cannot publish serialized module for " + wasm_path);
return("");
}
private:
static String cached_wasm_path(const String& wasm_path)
{