Profile request execution phases

This commit is contained in:
udo
2026-07-16 15:12:13 +00:00
parent 62adc7a6a9
commit dc5ccee805
4 changed files with 85 additions and 19 deletions
+70 -14
View File
@@ -99,16 +99,29 @@ struct WasmWorkerConfig
std::set<String> hostcall_blocklist;
};
struct WasmResponse
struct WasmRequestProfile
{
u64 dispatch_us = 0;
u64 workspace_setup_us = 0;
u64 workspace_birth_us = 0;
u64 context_apply_us = 0;
u64 component_resolve_count = 0;
u64 component_resolve_total_us = 0;
u64 hostcall_count = 0;
u64 hostcall_total_us = 0;
u64 mysql_hostcall_count = 0;
u64 mysql_hostcall_total_us = 0;
u64 memcache_hostcall_count = 0;
u64 memcache_hostcall_total_us = 0;
};
struct WasmResponse : WasmRequestProfile
{
bool ok = false;
bool handler_present = true; // false → unit has no handler for the requested kind (404)
String body;
DValue meta; // status / headers / cookies / session
String error; // collapsed trace or loader error when !ok
u64 workspace_birth_us = 0;
u64 component_resolve_count = 0;
u64 component_resolve_total_us = 0;
};
static u64 wasm_file_lock_timeout_ms()
@@ -764,14 +777,11 @@ private:
// ---- workspace (per request) ----------------------------------------------
class WasmWorkspace
class WasmWorkspace : public WasmRequestProfile
{
public:
WasmWorker& worker;
wasmtime::Store store;
u64 workspace_birth_us = 0;
u64 component_resolve_count = 0;
u64 component_resolve_total_us = 0;
struct FileHandle
{
@@ -1675,7 +1685,29 @@ private:
WasmWorkspace* self = this;
auto add = [&](auto&& callback) -> Extern {
Func func(cx, func_type, callback);
String profile_name = name;
auto profiled = [self, callback, profile_name](Caller caller, Span<const Val> args, Span<Val> results) mutable -> Result<std::monostate, Trap> {
auto started = std::chrono::steady_clock::now();
auto result = callback(caller, args, results);
if(profile_name != "uce_host_request_perf")
{
u64 elapsed = (u64)std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - started).count();
self->hostcall_count++;
self->hostcall_total_us += elapsed;
if(profile_name == "uce_host_mysql")
{
self->mysql_hostcall_count++;
self->mysql_hostcall_total_us += elapsed;
}
else if(profile_name == "uce_host_memcache_command")
{
self->memcache_hostcall_count++;
self->memcache_hostcall_total_us += elapsed;
}
}
return(result);
};
Func func(cx, func_type, profiled);
host_funcs.push_back(func);
return(host_funcs.back());
};
@@ -1727,8 +1759,21 @@ private:
response["running_us"] = (f64)((now - self->request_perf.time_start) * 1000000.0);
if(self->request_perf.time_init > 0)
response["total_us"] = (f64)((now - self->request_perf.time_init) * 1000000.0);
if(self->workspace_birth_us > 0)
response["workspace_birth_us"] = (f64)self->workspace_birth_us;
response["dispatch_us"] = (f64)self->dispatch_us;
response["workspace_setup_us"] = (f64)self->workspace_setup_us;
response["workspace_birth_us"] = (f64)self->workspace_birth_us;
response["context_apply_us"] = (f64)self->context_apply_us;
response["hostcall_count"] = (f64)self->hostcall_count;
response["hostcall_us"] = (f64)self->hostcall_total_us;
response["mysql_hostcall_count"] = (f64)self->mysql_hostcall_count;
response["mysql_hostcall_us"] = (f64)self->mysql_hostcall_total_us;
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_resolve_us"] = (f64)self->component_resolve_total_us;
f64 running_us = response["running_us"].to_f64();
f64 accounted_us = (f64)(self->dispatch_us + self->workspace_setup_us + self->workspace_birth_us + self->context_apply_us + self->hostcall_total_us);
response["guest_us"] = running_us > accounted_us ? running_us - accounted_us : 0.0;
}
encoded = ucb_encode(response);
if(args[2].i32() == 0)
@@ -2776,22 +2821,33 @@ inline WasmResponse wasm_worker_serve(WasmWorker& worker, const DValue& context_
const String& handler = "render", const Request* request = 0)
{
WasmResponse response;
f64 serve_started = time_precise();
auto workspace_start = std::chrono::steady_clock::now();
WasmWorkspace workspace(worker);
workspace.workspace_setup_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - workspace_start).count();
if(request)
{
workspace.set_perf_snapshot(my_pid, (u64)parent_pid, request->server ? request->server->request_count : 0, request->stats.time_init, request->stats.time_start);
if(request->stats.time_start > 0 && serve_started > request->stats.time_start)
workspace.dispatch_us = (u64)((serve_started - request->stats.time_start) * 1000000.0);
}
auto birth_start = std::chrono::steady_clock::now();
String error = workspace.birth();
workspace.workspace_birth_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - birth_start).count();
if(error == "")
{
auto context_start = std::chrono::steady_clock::now();
error = workspace.apply_context(context_tree);
workspace.context_apply_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - context_start).count();
}
if(error == "")
error = workspace.invoke_entry(entry_source_path, handler, &response.handler_present);
if(error == "")
error = workspace.collect(response);
response.workspace_birth_us = workspace.workspace_birth_us;
response.component_resolve_count = workspace.component_resolve_count;
response.component_resolve_total_us = workspace.component_resolve_total_us;
static_cast<WasmRequestProfile&>(response) = workspace;
if(error != "")
{
response.ok = false;