Reuse loaded component units per request
This commit is contained in:
@@ -139,8 +139,12 @@ The request entry unit is already loaded by the host, so its selected handler
|
|||||||
and optional `ONCE` export are placed directly into the workspace table and
|
and optional `ONCE` export are placed directly into the workspace table and
|
||||||
passed to `uce_wasm_invoke_loaded_entry()`. Dynamic component and unit calls
|
passed to `uce_wasm_invoke_loaded_entry()`. Dynamic component and unit calls
|
||||||
continue through `wasm_resolve_target()`, where relative-path resolution is
|
continue through `wasm_resolve_target()`, where relative-path resolution is
|
||||||
required. Opt-in verbose response headers split entry invocation into load,
|
required. Handler cache keys include the calling unit so identically named
|
||||||
presence lookup, table linking, and core dispatch time.
|
relative targets in different directories cannot alias. Once a unit has passed
|
||||||
|
freshness checks and loaded into a request workspace, later handler lookups
|
||||||
|
reuse that immutable request-local instance; `component_loaded_reuse_count`
|
||||||
|
reports those lookups. Opt-in verbose response headers split entry invocation
|
||||||
|
into load, presence lookup, table linking, and core dispatch time.
|
||||||
|
|
||||||
`wasm_backend_should_handle(request, entry_unit)` checks whether the wasm
|
`wasm_backend_should_handle(request, entry_unit)` checks whether the wasm
|
||||||
backend is initialized and the requested artifact/handler is currently
|
backend is initialized and the requested artifact/handler is currently
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ if [[ "$action" == "run" ]]; then
|
|||||||
scripts/test_dependency_invalidation.sh
|
scripts/test_dependency_invalidation.sh
|
||||||
scripts/test_cold_component_deadline.sh
|
scripts/test_cold_component_deadline.sh
|
||||||
scripts/test_nested_component_props.sh
|
scripts/test_nested_component_props.sh
|
||||||
|
scripts/test_relative_component_cache.sh
|
||||||
scripts/test_password_hashing.sh
|
scripts/test_password_hashing.sh
|
||||||
scripts/test_mysql_epoch_refresh.sh
|
scripts/test_mysql_epoch_refresh.sh
|
||||||
scripts/test_mysql_persistent_pool.sh
|
scripts/test_mysql_persistent_pool.sh
|
||||||
|
|||||||
Executable
+38
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
test_name="relative-component-cache-test-$$"
|
||||||
|
site_directory="${UCE_TEST_SITE_DIRECTORY:-site}"
|
||||||
|
if [[ -z "${UCE_TEST_SITE_DIRECTORY:-}" && -r /etc/uce/settings.cfg ]]; then
|
||||||
|
configured_site_directory=$(awk -F= '/^[[:space:]]*SITE_DIRECTORY[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2; exit}' /etc/uce/settings.cfg)
|
||||||
|
if [[ -n "${configured_site_directory:-}" ]]; then
|
||||||
|
site_directory="$configured_site_directory"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
source_dir="$site_directory/$test_name"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -rf "$source_dir"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
mkdir -p "$source_dir/a" "$source_dir/b"
|
||||||
|
|
||||||
|
printf '%s\n' \
|
||||||
|
'CLI(Request& context) {' \
|
||||||
|
' print(component("a/parent", context));' \
|
||||||
|
' print("/");' \
|
||||||
|
' print(component("b/parent", context));' \
|
||||||
|
'}' >"$source_dir/entry.uce"
|
||||||
|
printf '%s\n' 'COMPONENT(Request& context) { print(component("child", context)); }' >"$source_dir/a/parent.uce"
|
||||||
|
printf '%s\n' 'COMPONENT(Request& context) { print("relative-a"); }' >"$source_dir/a/child.uce"
|
||||||
|
printf '%s\n' 'COMPONENT(Request& context) { print(component("child", context)); }' >"$source_dir/b/parent.uce"
|
||||||
|
printf '%s\n' 'COMPONENT(Request& context) { print("relative-b"); }' >"$source_dir/b/child.uce"
|
||||||
|
|
||||||
|
output=$(scripts/uce-cli "/$test_name/entry.uce")
|
||||||
|
if [[ "$output" != "relative-a/relative-b" ]]; then
|
||||||
|
echo "relative component cache crossed caller boundaries: $output" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "relative component cache passed"
|
||||||
@@ -59,7 +59,7 @@ RENDER(Request& context)
|
|||||||
String unit_operations = json_encode(perf["unit_module_operations"]);
|
String unit_operations = json_encode(perf["unit_module_operations"]);
|
||||||
check(
|
check(
|
||||||
"request_perf() separates entry code from dynamic component materialization",
|
"request_perf() separates entry code from dynamic component materialization",
|
||||||
perf["entry_unit_load_count"].to_u64() == 1 && perf["entry_unit_materialize_us"].to_u64() > 0 && perf["dynamic_include_load_count"].to_u64() > 0 && perf["dynamic_include_materialize_us"].to_u64() > 0 && unit_operations.find("\"kind\": \"entry\"") != String::npos && unit_operations.find("\"kind\": \"component\"") != String::npos && unit_operations.find("\"materialize_us\"") != String::npos,
|
perf["entry_unit_load_count"].to_u64() == 1 && perf["entry_unit_materialize_us"].to_u64() > 0 && perf["dynamic_include_load_count"].to_u64() > 0 && perf["dynamic_include_materialize_us"].to_u64() > 0 && perf["component_loaded_reuse_count"].to_u64() > 0 && unit_operations.find("\"kind\": \"entry\"") != String::npos && unit_operations.find("\"kind\": \"component\"") != String::npos && unit_operations.find("\"materialize_us\"") != String::npos,
|
||||||
unit_operations
|
unit_operations
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -181,11 +181,12 @@ RENDER(Request& context)
|
|||||||
u64 dropped_hostcall_operations = perf["hostcall_operations_dropped"].to_u64();
|
u64 dropped_hostcall_operations = perf["hostcall_operations_dropped"].to_u64();
|
||||||
hostcall_operation_profile_valid = hostcall_operation_profile_valid && perf["hostcall_cpu_profiled"].type == 'B' && perf["hostcall_cpu_us"].to_u64() <= perf["hostcall_us"].to_u64() + 2 && operation_kinds > 0 && operation_kinds <= 32 && ((dropped_hostcall_operations == 0 && operation_hostcalls == perf["hostcall_count"].to_u64() && operation_hostcall_us == perf["hostcall_us"].to_u64() && operation_hostcall_cpu_us == perf["hostcall_cpu_us"].to_u64()) || (dropped_hostcall_operations > 0 && operation_kinds == 32 && operation_hostcalls < perf["hostcall_count"].to_u64() && operation_hostcall_us <= perf["hostcall_us"].to_u64() && operation_hostcall_cpu_us <= perf["hostcall_cpu_us"].to_u64()));
|
hostcall_operation_profile_valid = hostcall_operation_profile_valid && perf["hostcall_cpu_profiled"].type == 'B' && perf["hostcall_cpu_us"].to_u64() <= perf["hostcall_us"].to_u64() + 2 && operation_kinds > 0 && operation_kinds <= 32 && ((dropped_hostcall_operations == 0 && operation_hostcalls == perf["hostcall_count"].to_u64() && operation_hostcall_us == perf["hostcall_us"].to_u64() && operation_hostcall_cpu_us == perf["hostcall_cpu_us"].to_u64()) || (dropped_hostcall_operations > 0 && operation_kinds == 32 && operation_hostcalls < perf["hostcall_count"].to_u64() && operation_hostcall_us <= perf["hostcall_us"].to_u64() && operation_hostcall_cpu_us <= perf["hostcall_cpu_us"].to_u64()));
|
||||||
bool thread_runtime_profile_valid = perf["thread_runtime_profiled"].type == 'B' && (!perf["thread_runtime_profiled"].to_bool() || (perf["thread_cpu_start"].to_f64() >= 0 && perf["thread_cpu_end"].to_f64() >= 0 && perf["thread_cpu_migrated"].type == 'B' && perf["thread_user_cpu_us"].to_u64() + perf["thread_system_cpu_us"].to_u64() <= perf["workspace_wall_us"].to_u64() + 5 && perf["thread_voluntary_context_switches"].type != 'S' && perf["thread_involuntary_context_switches"].type != 'S' && perf["thread_minor_faults"].type != 'S' && perf["thread_major_faults"].type != 'S'));
|
bool thread_runtime_profile_valid = perf["thread_runtime_profiled"].type == 'B' && (!perf["thread_runtime_profiled"].to_bool() || (perf["thread_cpu_start"].to_f64() >= 0 && perf["thread_cpu_end"].to_f64() >= 0 && perf["thread_cpu_migrated"].type == 'B' && perf["thread_user_cpu_us"].to_u64() + perf["thread_system_cpu_us"].to_u64() <= perf["workspace_wall_us"].to_u64() + 5 && perf["thread_voluntary_context_switches"].type != 'S' && perf["thread_involuntary_context_switches"].type != 'S' && perf["thread_minor_faults"].type != 'S' && perf["thread_major_faults"].type != 'S'));
|
||||||
bool perf_stable = transport_profile_valid && workspace_cpu_profile_valid && unit_module_profile_valid && hostcall_operation_profile_valid && thread_runtime_profile_valid && perf["worker_pid"].to_u64() > 0 && perf["running_us"].to_f64() > 0 && perf["dispatch_us"].type != 'S' && perf["workspace_setup_us"].type != 'S' && perf["workspace_birth_us"].type != 'S' && perf["context_apply_us"].type != 'S' && perf["hostcall_count"].to_u64() > 0 && perf["hostcall_us"].type != 'S' && perf["guest_us"].to_f64() > 0 && perf["component_resolve_count"].type != 'S' && perf["component_path_us"].type != 'S' && perf["component_artifact_us"].type != 'S' && perf["component_load_us"].type != 'S' && perf["component_link_us"].type != 'S' && perf["unit_load_count"].to_u64() > 0 && perf["unit_module_us"].type != 'S' && perf["unit_allocate_us"].type != 'S' && perf["unit_import_us"].type != 'S' && perf["unit_symbol_resolve_count"].type != 'S' && perf["unit_symbol_resolve_us"].type != 'S' && perf["unit_instantiate_us"].type != 'S' && perf["unit_initialize_us"].type != 'S';
|
bool perf_stable = transport_profile_valid && workspace_cpu_profile_valid && unit_module_profile_valid && hostcall_operation_profile_valid && thread_runtime_profile_valid && perf["worker_pid"].to_u64() > 0 && perf["running_us"].to_f64() > 0 && perf["dispatch_us"].type != 'S' && perf["workspace_setup_us"].type != 'S' && perf["workspace_birth_us"].type != 'S' && perf["context_apply_us"].type != 'S' && perf["hostcall_count"].to_u64() > 0 && perf["hostcall_us"].type != 'S' && perf["guest_us"].to_f64() > 0 && perf["component_resolve_count"].type != 'S' && perf["component_loaded_reuse_count"].type != 'S' && perf["component_path_us"].type != 'S' && perf["component_artifact_us"].type != 'S' && perf["component_load_us"].type != 'S' && perf["component_link_us"].type != 'S' && perf["unit_load_count"].to_u64() > 0 && perf["unit_module_us"].type != 'S' && perf["unit_allocate_us"].type != 'S' && perf["unit_import_us"].type != 'S' && perf["unit_symbol_resolve_count"].type != 'S' && perf["unit_symbol_resolve_us"].type != 'S' && perf["unit_instantiate_us"].type != 'S' && perf["unit_initialize_us"].type != 'S';
|
||||||
u64 profiled_hostcalls = perf["hostcall_count"].to_u64();
|
u64 profiled_hostcalls = perf["hostcall_count"].to_u64();
|
||||||
f64 profiled_hostcall_us = perf["hostcall_us"].to_f64();
|
f64 profiled_hostcall_us = perf["hostcall_us"].to_f64();
|
||||||
u64 profiled_hostcall_cpu_us = perf["hostcall_cpu_us"].to_u64();
|
u64 profiled_hostcall_cpu_us = perf["hostcall_cpu_us"].to_u64();
|
||||||
u64 profiled_components = perf["component_resolve_count"].to_u64();
|
u64 profiled_components = perf["component_resolve_count"].to_u64();
|
||||||
|
u64 profiled_component_loaded_reuses = perf["component_loaded_reuse_count"].to_u64();
|
||||||
u64 profiled_component_path = perf["component_path_us"].to_u64();
|
u64 profiled_component_path = perf["component_path_us"].to_u64();
|
||||||
u64 profiled_component_artifact = perf["component_artifact_us"].to_u64();
|
u64 profiled_component_artifact = perf["component_artifact_us"].to_u64();
|
||||||
u64 profiled_component_load = perf["component_load_us"].to_u64();
|
u64 profiled_component_load = perf["component_load_us"].to_u64();
|
||||||
@@ -203,7 +204,7 @@ RENDER(Request& context)
|
|||||||
for(u64 i = 0; i < 512 && perf_stable; i++)
|
for(u64 i = 0; i < 512 && perf_stable; i++)
|
||||||
{
|
{
|
||||||
perf = request_perf();
|
perf = request_perf();
|
||||||
perf_stable = perf["worker_pid"].to_u64() > 0 && perf["running_us"].to_f64() > 0 && perf["dispatch_us"].type != 'S' && perf["workspace_setup_us"].type != 'S' && perf["workspace_birth_us"].type != 'S' && perf["context_apply_us"].type != 'S' && perf["hostcall_count"].to_u64() == profiled_hostcalls && perf["hostcall_us"].to_f64() == profiled_hostcall_us && perf["hostcall_cpu_us"].to_u64() == profiled_hostcall_cpu_us && perf["guest_us"].to_f64() > 0 && perf["component_resolve_count"].to_u64() == profiled_components && perf["component_path_us"].to_u64() == profiled_component_path && perf["component_artifact_us"].to_u64() == profiled_component_artifact && perf["component_load_us"].to_u64() == profiled_component_load && perf["component_link_us"].to_u64() == profiled_component_link && perf["unit_load_count"].to_u64() == profiled_unit_loads && perf["unit_module_us"].to_u64() == profiled_unit_module && perf["unit_allocate_us"].to_u64() == profiled_unit_allocate && perf["unit_import_us"].to_u64() == profiled_unit_import && perf["unit_symbol_resolve_count"].to_u64() == profiled_unit_symbol_resolve_count && perf["unit_symbol_resolve_us"].to_u64() == profiled_unit_symbol_resolve && perf["unit_instantiate_us"].to_u64() == profiled_unit_instantiate && perf["unit_initialize_us"].to_u64() == profiled_unit_initialize && json_encode(perf["mysql_operations"]) == profiled_mysql_operations && json_encode(perf["hostcall_operations"]) == profiled_hostcall_operations;
|
perf_stable = perf["worker_pid"].to_u64() > 0 && perf["running_us"].to_f64() > 0 && perf["dispatch_us"].type != 'S' && perf["workspace_setup_us"].type != 'S' && perf["workspace_birth_us"].type != 'S' && perf["context_apply_us"].type != 'S' && perf["hostcall_count"].to_u64() == profiled_hostcalls && perf["hostcall_us"].to_f64() == profiled_hostcall_us && perf["hostcall_cpu_us"].to_u64() == profiled_hostcall_cpu_us && perf["guest_us"].to_f64() > 0 && perf["component_resolve_count"].to_u64() == profiled_components && perf["component_loaded_reuse_count"].to_u64() == profiled_component_loaded_reuses && perf["component_path_us"].to_u64() == profiled_component_path && perf["component_artifact_us"].to_u64() == profiled_component_artifact && perf["component_load_us"].to_u64() == profiled_component_load && perf["component_link_us"].to_u64() == profiled_component_link && perf["unit_load_count"].to_u64() == profiled_unit_loads && perf["unit_module_us"].to_u64() == profiled_unit_module && perf["unit_allocate_us"].to_u64() == profiled_unit_allocate && perf["unit_import_us"].to_u64() == profiled_unit_import && perf["unit_symbol_resolve_count"].to_u64() == profiled_unit_symbol_resolve_count && perf["unit_symbol_resolve_us"].to_u64() == profiled_unit_symbol_resolve && perf["unit_instantiate_us"].to_u64() == profiled_unit_instantiate && perf["unit_initialize_us"].to_u64() == profiled_unit_initialize && json_encode(perf["mysql_operations"]) == profiled_mysql_operations && json_encode(perf["hostcall_operations"]) == profiled_hostcall_operations;
|
||||||
}
|
}
|
||||||
check("request_perf() stages stable repeated snapshots", perf_stable, json_encode(perf));
|
check("request_perf() stages stable repeated snapshots", perf_stable, json_encode(perf));
|
||||||
|
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ String wasm_backend_serve(Request& request, const String& entry_unit, const Stri
|
|||||||
request.header["X-UCE-Wasm-Entry-Dispatch-Us"] = std::to_string(response.entry_dispatch_us);
|
request.header["X-UCE-Wasm-Entry-Dispatch-Us"] = std::to_string(response.entry_dispatch_us);
|
||||||
request.header["X-UCE-Wasm-Output-Collect-Us"] = std::to_string(response.output_collect_us);
|
request.header["X-UCE-Wasm-Output-Collect-Us"] = std::to_string(response.output_collect_us);
|
||||||
request.header["X-UCE-Wasm-Component-Resolve-Count"] = std::to_string(response.component_resolve_count);
|
request.header["X-UCE-Wasm-Component-Resolve-Count"] = std::to_string(response.component_resolve_count);
|
||||||
|
request.header["X-UCE-Wasm-Component-Loaded-Reuse-Count"] = std::to_string(response.component_loaded_reuse_count);
|
||||||
request.header["X-UCE-Wasm-Component-Resolve-Total-Us"] = std::to_string(response.component_resolve_total_us);
|
request.header["X-UCE-Wasm-Component-Resolve-Total-Us"] = std::to_string(response.component_resolve_total_us);
|
||||||
request.header["X-UCE-Wasm-Component-Resolve-Avg-Us"] = std::to_string(
|
request.header["X-UCE-Wasm-Component-Resolve-Avg-Us"] = std::to_string(
|
||||||
response.component_resolve_count ? response.component_resolve_total_us / response.component_resolve_count : 0);
|
response.component_resolve_count ? response.component_resolve_total_us / response.component_resolve_count : 0);
|
||||||
|
|||||||
+2
-2
@@ -543,7 +543,8 @@ struct RequestPropsScope
|
|||||||
// probe that loads nothing). No per-mode kinds.
|
// probe that loads nothing). No per-mode kinds.
|
||||||
static s32 wasm_resolve_target(String unit_target, String handler, String* resolved_out = 0)
|
static s32 wasm_resolve_target(String unit_target, String handler, String* resolved_out = 0)
|
||||||
{
|
{
|
||||||
String cache_key = handler + "\t" + unit_target;
|
String current = context ? context->resources.current_unit_file : "";
|
||||||
|
String cache_key = current + "\t" + handler + "\t" + unit_target;
|
||||||
bool is_exists = (handler == "exists");
|
bool is_exists = (handler == "exists");
|
||||||
auto cached = wasm_component_slots.find(cache_key);
|
auto cached = wasm_component_slots.find(cache_key);
|
||||||
if(cached != wasm_component_slots.end() && !is_exists)
|
if(cached != wasm_component_slots.end() && !is_exists)
|
||||||
@@ -553,7 +554,6 @@ static s32 wasm_resolve_target(String unit_target, String handler, String* resol
|
|||||||
return(cached->second);
|
return(cached->second);
|
||||||
}
|
}
|
||||||
char resolved[512];
|
char resolved[512];
|
||||||
String current = context ? context->resources.current_unit_file : "";
|
|
||||||
s32 slot = uce_host_component_resolve(
|
s32 slot = uce_host_component_resolve(
|
||||||
unit_target.data(), unit_target.size(), handler.data(), handler.size(),
|
unit_target.data(), unit_target.size(), handler.data(), handler.size(),
|
||||||
current.data(), current.size(),
|
current.data(), current.size(),
|
||||||
|
|||||||
+81
-55
@@ -201,6 +201,7 @@ struct WasmRequestProfile
|
|||||||
u64 output_collect_us = 0;
|
u64 output_collect_us = 0;
|
||||||
u64 workspace_complete_us = 0;
|
u64 workspace_complete_us = 0;
|
||||||
u64 component_resolve_count = 0;
|
u64 component_resolve_count = 0;
|
||||||
|
u64 component_loaded_reuse_count = 0;
|
||||||
u64 component_resolve_total_us = 0;
|
u64 component_resolve_total_us = 0;
|
||||||
u64 component_path_total_us = 0;
|
u64 component_path_total_us = 0;
|
||||||
u64 component_artifact_total_us = 0;
|
u64 component_artifact_total_us = 0;
|
||||||
@@ -1732,6 +1733,7 @@ private:
|
|||||||
};
|
};
|
||||||
std::vector<LoadedUnit> units;
|
std::vector<LoadedUnit> units;
|
||||||
std::map<String, size_t> units_by_source;
|
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
|
std::map<String, u32> handler_slots; // source + ":" + symbol → table slot
|
||||||
bool stale_component_mutation_blocked = false;
|
bool stale_component_mutation_blocked = false;
|
||||||
String stale_component_mutation_status;
|
String stale_component_mutation_status;
|
||||||
@@ -2386,7 +2388,27 @@ private:
|
|||||||
return(0);
|
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>(
|
component_path_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
||||||
std::chrono::steady_clock::now() - probe_start).count();
|
std::chrono::steady_clock::now() - probe_start).count();
|
||||||
if(resolved == "")
|
if(resolved == "")
|
||||||
@@ -2401,67 +2423,70 @@ private:
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto artifact_start = std::chrono::steady_clock::now();
|
if(!loaded_reuse)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
component_source_generation = compiler_source_generation(context);
|
auto artifact_start = std::chrono::steady_clock::now();
|
||||||
component_source_generation_checked = true;
|
bool artifact_exists = file_exists_host(worker.unit_wasm_path(resolved));
|
||||||
}
|
bool can_serve_stale = compiler_request_can_serve_stale_artifact(context);
|
||||||
bool stale = false;
|
String method = context ? to_upper(trim(context->params["REQUEST_METHOD"])) : String("");
|
||||||
if(artifact_exists)
|
bool read_request = method == "GET" || method == "HEAD" || method == "OPTIONS";
|
||||||
{
|
if(can_serve_stale && read_request && !component_source_generation_checked)
|
||||||
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);
|
component_source_generation = compiler_source_generation(context);
|
||||||
worker.component_freshness[resolved] = { now, stale, component_source_generation };
|
component_source_generation_checked = true;
|
||||||
}
|
}
|
||||||
else
|
bool stale = false;
|
||||||
stale = cached_freshness->second.stale;
|
if(artifact_exists)
|
||||||
}
|
|
||||||
if(stale && can_serve_stale)
|
|
||||||
{
|
|
||||||
compiler_prioritize_unit(context, resolved);
|
|
||||||
if(!read_request)
|
|
||||||
{
|
{
|
||||||
stale_component_mutation_blocked = true;
|
auto now = std::chrono::steady_clock::now();
|
||||||
stale_component_mutation_status = context->params["GATEWAY_INTERFACE"] != "" ?
|
auto cached_freshness = worker.component_freshness.find(resolved);
|
||||||
"Status: 503 Service Unavailable" : "HTTP/1.1 503 Service Unavailable";
|
// HTTP reads may serve a complete stale artifact, so bound their graph
|
||||||
component_artifact_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
|
// stat work; CLI and mutations always check the current graph.
|
||||||
std::chrono::steady_clock::now() - artifact_start).count();
|
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();
|
record_probe();
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
}
|
component_loaded_paths[resolve_key] = resolved;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
auto link_start = std::chrono::steady_clock::now();
|
auto link_start = std::chrono::steady_clock::now();
|
||||||
auto record_link = [&]() {
|
auto record_link = [&]() {
|
||||||
@@ -2723,6 +2748,7 @@ private:
|
|||||||
response["memcache_hostcall_count"] = (f64)self->memcache_hostcall_count;
|
response["memcache_hostcall_count"] = (f64)self->memcache_hostcall_count;
|
||||||
response["memcache_hostcall_us"] = (f64)self->memcache_hostcall_total_us;
|
response["memcache_hostcall_us"] = (f64)self->memcache_hostcall_total_us;
|
||||||
response["component_resolve_count"] = (f64)self->component_resolve_count;
|
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_resolve_us"] = (f64)self->component_resolve_total_us;
|
||||||
response["component_path_us"] = (f64)self->component_path_total_us;
|
response["component_path_us"] = (f64)self->component_path_total_us;
|
||||||
response["component_artifact_us"] = (f64)self->component_artifact_total_us;
|
response["component_artifact_us"] = (f64)self->component_artifact_total_us;
|
||||||
|
|||||||
Reference in New Issue
Block a user