Keep hostcall CPU profiling off hot paths
This commit is contained in:
parent
c15fdc3346
commit
5a5450caa8
@ -38,7 +38,7 @@ WASM_COMPILE_SCRIPT=scripts/compile_wasm_unit
|
||||
|
||||
# WASM RUNTIME SETTINGS. Unit execution is always routed through wasm.
|
||||
WASM_BACKEND_VERBOSE=0
|
||||
WASM_PROFILE_HOSTCALL_CPU=1
|
||||
WASM_PROFILE_HOSTCALL_CPU=0
|
||||
WASM_CORE_PATH=bin/wasm/core.wasm
|
||||
WASM_MEMORY_LIMIT_BYTES=536870912
|
||||
WASM_EPOCH_DEADLINE_TICKS=200
|
||||
|
||||
@ -11,7 +11,7 @@ return value : performance snapshot for the active request/workspace
|
||||
:content
|
||||
Returns a DValue with timing and process metadata such as worker pid, parent pid, request count, request start times, native dispatch, workspace setup and birth, context application, guest execution, and hostcall timing. `accept_us` is divided into `transport_params_us` (FastCGI begin through the end of parameters), `transport_input_us` (parameters through the end of input), and `handler_queue_us` (input close through handler entry). This distinguishes upstream request delivery from work inside the UCE handler.
|
||||
|
||||
Hostcall totals include component resolution; `hostcall_cpu_us` separates thread CPU from hostcall wall time, and each bounded `hostcall_operations` item includes the same `cpu_us` attribution. `WASM_PROFILE_HOSTCALL_CPU=0` disables those per-hostcall thread-CPU samples and leaves their counters at zero when profiling cost matters more than that split. MySQL, memcache, and component resolution also expose their own count and microsecond fields. Workspace setup, birth, and context application expose matching wall and thread-CPU microseconds. `execution_cpu_us` is the remaining workspace thread CPU through the snapshot after those three phases. `unit_module_operations` is a source-root-relative list of up to 32 unit loads. Each item attributes module lookup/read/parse/build/classification plus allocation, import construction, symbol resolution, instantiation, and initialization; no caller-supplied paths are exposed. `mysql_operations` is an ordered, query-text-free list of up to 64 logical MySQL operations and their microsecond durations. A connect operation also identifies its source as `new`, cross-request `worker`, or same-request `request`; the corresponding `mysql_connection_open_count`, `mysql_connection_reuse_count`, and `mysql_request_pool_hit_count` fields provide totals. `mysql_operations_dropped` reports any overflow. The profiling hostcall itself is excluded from those totals so repeated snapshots remain comparable.
|
||||
Hostcall totals include component resolution. When `WASM_PROFILE_HOSTCALL_CPU=1`, `hostcall_cpu_us` separates thread CPU from hostcall wall time and each bounded `hostcall_operations` item includes the same `cpu_us` attribution. This diagnostic is off by default because sampling thread CPU around every hostcall adds hot-path cost; `hostcall_cpu_profiled` identifies whether the current request used it, and disabled counters remain zero. MySQL, memcache, and component resolution also expose their own count and microsecond fields. Workspace setup, birth, and context application expose matching wall and thread-CPU microseconds. `execution_cpu_us` is the remaining workspace thread CPU through the snapshot after those three phases. `unit_module_operations` is a source-root-relative list of up to 32 unit loads. Each item attributes module lookup/read/parse/build/classification plus allocation, import construction, symbol resolution, instantiation, and initialization; no caller-supplied paths are exposed. `mysql_operations` is an ordered, query-text-free list of up to 64 logical MySQL operations and their microsecond durations. A connect operation also identifies its source as `new`, cross-request `worker`, or same-request `request`; the corresponding `mysql_connection_open_count`, `mysql_connection_reuse_count`, and `mysql_request_pool_hit_count` fields provide totals. `mysql_operations_dropped` reports any overflow. The profiling hostcall itself is excluded from those totals so repeated snapshots remain comparable.
|
||||
|
||||
Component resolution is divided into `component_path_us`, `component_artifact_us`, `component_load_us`, and `component_link_us`. These aggregate path resolution, artifact readiness/freshness, Wasmtime side-module loading, and exported-handler lookup/table placement without exposing source paths.
|
||||
|
||||
|
||||
@ -177,7 +177,7 @@ RENDER(Request& context)
|
||||
hostcall_operation_profile_valid = hostcall_operation_profile_valid && name != "" && !contains(name, "uce_host_") && !contains(name, "/") && operation["count"].to_u64() > 0 && operation["cpu_us"].to_u64() <= operation["us"].to_u64() + 2;
|
||||
});
|
||||
u64 dropped_hostcall_operations = perf["hostcall_operations_dropped"].to_u64();
|
||||
hostcall_operation_profile_valid = hostcall_operation_profile_valid && 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 perf_stable = transport_profile_valid && workspace_cpu_profile_valid && unit_module_profile_valid && hostcall_operation_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';
|
||||
u64 profiled_hostcalls = perf["hostcall_count"].to_u64();
|
||||
f64 profiled_hostcall_us = perf["hostcall_us"].to_f64();
|
||||
|
||||
@ -1676,7 +1676,7 @@ StringMap make_server_settings()
|
||||
cfg["BIN_DIRECTORY"] = "/tmp/uce/work";
|
||||
cfg["WASM_COMPILE_SCRIPT"] = "scripts/compile_wasm_unit";
|
||||
cfg["WASM_BACKEND_VERBOSE"] = "0";
|
||||
cfg["WASM_PROFILE_HOSTCALL_CPU"] = "1";
|
||||
cfg["WASM_PROFILE_HOSTCALL_CPU"] = "0";
|
||||
cfg["WASM_CORE_PATH"] = "";
|
||||
cfg["WASM_MEMORY_LIMIT_BYTES"] = std::to_string(512ull * 1024 * 1024);
|
||||
cfg["WASM_EPOCH_DEADLINE_TICKS"] = "200";
|
||||
|
||||
@ -53,7 +53,7 @@ static String wasm_backend_ensure_started(Request* context)
|
||||
wc.memory_limit = (int64_t)to_u64(cfg["WASM_MEMORY_LIMIT_BYTES"], 512ull * 1024 * 1024);
|
||||
wc.epoch_deadline_ticks = to_u64(cfg["WASM_EPOCH_DEADLINE_TICKS"], 200);
|
||||
wc.mysql_persistent_pool_size = std::min<u64>(to_u64(cfg["MYSQL_PERSISTENT_POOL_SIZE"], 8), 64);
|
||||
wc.profile_hostcall_cpu = to_bool(cfg["WASM_PROFILE_HOSTCALL_CPU"], true);
|
||||
wc.profile_hostcall_cpu = to_bool(cfg["WASM_PROFILE_HOSTCALL_CPU"], false);
|
||||
wc.verbose = to_bool(cfg["WASM_BACKEND_VERBOSE"], false);
|
||||
// UCE_HOSTCALL_BLOCKLIST: comma-separated uce_host_* names (with or without
|
||||
// the "uce_host_" prefix) the sysadmin disables; each blocked call traps into
|
||||
|
||||
@ -125,7 +125,7 @@ struct WasmWorkerConfig
|
||||
u32 table_headroom = 4096;
|
||||
u64 epoch_deadline_ticks = 200; // ticker period × ticks = CPU budget
|
||||
u64 mysql_persistent_pool_size = 8;
|
||||
bool profile_hostcall_cpu = true;
|
||||
bool profile_hostcall_cpu = false;
|
||||
bool verbose = false;
|
||||
// uce_host_* names (bare, without the "uce_host_" prefix) the sysadmin has
|
||||
// disabled via UCE_HOSTCALL_BLOCKLIST. A blocked hostcall resolves to a trap
|
||||
@ -2349,6 +2349,7 @@ private:
|
||||
response["execution_cpu_us"] = (f64)(workspace_cpu_us > phase_cpu_us ? workspace_cpu_us - phase_cpu_us : 0);
|
||||
response["hostcall_count"] = (f64)self->hostcall_count;
|
||||
response["hostcall_us"] = (f64)self->hostcall_total_us;
|
||||
response["hostcall_cpu_profiled"].set_bool(self->worker.cfg.profile_hostcall_cpu);
|
||||
response["hostcall_cpu_us"] = (f64)self->hostcall_cpu_total_us;
|
||||
std::vector<u64> invoked_hostcalls;
|
||||
for(u64 i = 0; i < self->hostcall_operation_slots; i++)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user