Reuse loaded component units per request
This commit is contained in:
+81
-55
@@ -201,6 +201,7 @@ struct WasmRequestProfile
|
||||
u64 output_collect_us = 0;
|
||||
u64 workspace_complete_us = 0;
|
||||
u64 component_resolve_count = 0;
|
||||
u64 component_loaded_reuse_count = 0;
|
||||
u64 component_resolve_total_us = 0;
|
||||
u64 component_path_total_us = 0;
|
||||
u64 component_artifact_total_us = 0;
|
||||
@@ -1732,6 +1733,7 @@ private:
|
||||
};
|
||||
std::vector<LoadedUnit> units;
|
||||
std::map<String, size_t> units_by_source;
|
||||
std::map<String, String> component_loaded_paths; // caller + target → request-loaded canonical source
|
||||
std::map<String, u32> handler_slots; // source + ":" + symbol → table slot
|
||||
bool stale_component_mutation_blocked = false;
|
||||
String stale_component_mutation_status;
|
||||
@@ -2386,7 +2388,27 @@ private:
|
||||
return(0);
|
||||
}
|
||||
|
||||
String resolved = resolve_source_path(file_name, current_unit);
|
||||
String resolve_key = current_unit + "\t" + file_name;
|
||||
String resolved;
|
||||
String error;
|
||||
size_t unit_index = 0;
|
||||
bool loaded_reuse = false;
|
||||
auto loaded = units_by_source.find(file_name);
|
||||
if(loaded == units_by_source.end())
|
||||
{
|
||||
auto known_path = component_loaded_paths.find(resolve_key);
|
||||
if(known_path != component_loaded_paths.end())
|
||||
loaded = units_by_source.find(known_path->second);
|
||||
}
|
||||
if(loaded != units_by_source.end())
|
||||
{
|
||||
resolved = loaded->first;
|
||||
unit_index = loaded->second;
|
||||
loaded_reuse = true;
|
||||
component_loaded_reuse_count++;
|
||||
}
|
||||
else
|
||||
resolved = resolve_source_path(file_name, current_unit);
|
||||
component_path_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - probe_start).count();
|
||||
if(resolved == "")
|
||||
@@ -2401,67 +2423,70 @@ private:
|
||||
return(1);
|
||||
}
|
||||
|
||||
auto artifact_start = std::chrono::steady_clock::now();
|
||||
bool artifact_exists = file_exists_host(worker.unit_wasm_path(resolved));
|
||||
bool can_serve_stale = compiler_request_can_serve_stale_artifact(context);
|
||||
String method = context ? to_upper(trim(context->params["REQUEST_METHOD"])) : String("");
|
||||
bool read_request = method == "GET" || method == "HEAD" || method == "OPTIONS";
|
||||
if(can_serve_stale && read_request && !component_source_generation_checked)
|
||||
if(!loaded_reuse)
|
||||
{
|
||||
component_source_generation = compiler_source_generation(context);
|
||||
component_source_generation_checked = true;
|
||||
}
|
||||
bool stale = false;
|
||||
if(artifact_exists)
|
||||
{
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
auto cached_freshness = worker.component_freshness.find(resolved);
|
||||
// HTTP reads may serve a complete stale artifact, so bound their graph
|
||||
// stat work; CLI and mutations always check the current graph.
|
||||
bool generation_available = component_source_generation != "";
|
||||
bool check_freshness = !can_serve_stale || !read_request ||
|
||||
cached_freshness == worker.component_freshness.end() ||
|
||||
(generation_available ?
|
||||
cached_freshness->second.source_generation != component_source_generation :
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - cached_freshness->second.checked_at).count() >= 1000);
|
||||
if(check_freshness)
|
||||
auto artifact_start = std::chrono::steady_clock::now();
|
||||
bool artifact_exists = file_exists_host(worker.unit_wasm_path(resolved));
|
||||
bool can_serve_stale = compiler_request_can_serve_stale_artifact(context);
|
||||
String method = context ? to_upper(trim(context->params["REQUEST_METHOD"])) : String("");
|
||||
bool read_request = method == "GET" || method == "HEAD" || method == "OPTIONS";
|
||||
if(can_serve_stale && read_request && !component_source_generation_checked)
|
||||
{
|
||||
stale = compiler_unit_needs_recompile(context, resolved, 0, can_serve_stale && read_request, true);
|
||||
worker.component_freshness[resolved] = { now, stale, component_source_generation };
|
||||
component_source_generation = compiler_source_generation(context);
|
||||
component_source_generation_checked = true;
|
||||
}
|
||||
else
|
||||
stale = cached_freshness->second.stale;
|
||||
}
|
||||
if(stale && can_serve_stale)
|
||||
{
|
||||
compiler_prioritize_unit(context, resolved);
|
||||
if(!read_request)
|
||||
bool stale = false;
|
||||
if(artifact_exists)
|
||||
{
|
||||
stale_component_mutation_blocked = true;
|
||||
stale_component_mutation_status = context->params["GATEWAY_INTERFACE"] != "" ?
|
||||
"Status: 503 Service Unavailable" : "HTTP/1.1 503 Service Unavailable";
|
||||
component_artifact_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - artifact_start).count();
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
auto cached_freshness = worker.component_freshness.find(resolved);
|
||||
// HTTP reads may serve a complete stale artifact, so bound their graph
|
||||
// stat work; CLI and mutations always check the current graph.
|
||||
bool generation_available = component_source_generation != "";
|
||||
bool check_freshness = !can_serve_stale || !read_request ||
|
||||
cached_freshness == worker.component_freshness.end() ||
|
||||
(generation_available ?
|
||||
cached_freshness->second.source_generation != component_source_generation :
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - cached_freshness->second.checked_at).count() >= 1000);
|
||||
if(check_freshness)
|
||||
{
|
||||
stale = compiler_unit_needs_recompile(context, resolved, 0, can_serve_stale && read_request, true);
|
||||
worker.component_freshness[resolved] = { now, stale, component_source_generation };
|
||||
}
|
||||
else
|
||||
stale = cached_freshness->second.stale;
|
||||
}
|
||||
if(stale && can_serve_stale)
|
||||
{
|
||||
compiler_prioritize_unit(context, resolved);
|
||||
if(!read_request)
|
||||
{
|
||||
stale_component_mutation_blocked = true;
|
||||
stale_component_mutation_status = context->params["GATEWAY_INTERFACE"] != "" ?
|
||||
"Status: 503 Service Unavailable" : "HTTP/1.1 503 Service Unavailable";
|
||||
component_artifact_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - artifact_start).count();
|
||||
record_probe();
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
if(!artifact_exists || (stale && !can_serve_stale))
|
||||
get_shared_unit(context, resolved);
|
||||
component_artifact_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - artifact_start).count();
|
||||
|
||||
auto load_start = std::chrono::steady_clock::now();
|
||||
error = load_unit(resolved, "component", unit_index);
|
||||
component_load_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - load_start).count();
|
||||
if(error != "")
|
||||
{
|
||||
fprintf(stderr, "[wasm] component load failed: %s\n", error.c_str());
|
||||
record_probe();
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
if(!artifact_exists || (stale && !can_serve_stale))
|
||||
get_shared_unit(context, resolved);
|
||||
component_artifact_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - artifact_start).count();
|
||||
|
||||
auto load_start = std::chrono::steady_clock::now();
|
||||
size_t unit_index = 0;
|
||||
String error = load_unit(resolved, "component", unit_index);
|
||||
component_load_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - load_start).count();
|
||||
if(error != "")
|
||||
{
|
||||
fprintf(stderr, "[wasm] component load failed: %s\n", error.c_str());
|
||||
record_probe();
|
||||
return(0);
|
||||
component_loaded_paths[resolve_key] = resolved;
|
||||
}
|
||||
auto link_start = std::chrono::steady_clock::now();
|
||||
auto record_link = [&]() {
|
||||
@@ -2723,6 +2748,7 @@ private:
|
||||
response["memcache_hostcall_count"] = (f64)self->memcache_hostcall_count;
|
||||
response["memcache_hostcall_us"] = (f64)self->memcache_hostcall_total_us;
|
||||
response["component_resolve_count"] = (f64)self->component_resolve_count;
|
||||
response["component_loaded_reuse_count"] = (f64)self->component_loaded_reuse_count;
|
||||
response["component_resolve_us"] = (f64)self->component_resolve_total_us;
|
||||
response["component_path_us"] = (f64)self->component_path_total_us;
|
||||
response["component_artifact_us"] = (f64)self->component_artifact_total_us;
|
||||
|
||||
Reference in New Issue
Block a user