Decode request maps directly into Wasm workspaces

This commit is contained in:
udo
2026-07-18 04:21:28 +00:00
parent 516ed94032
commit 5e140d6a5a
7 changed files with 218 additions and 111 deletions
+66 -17
View File
@@ -1266,6 +1266,58 @@ private:
std::vector<String> hostcall_operation_names;
};
// The request envelope keeps app scratch state separate from transport fields.
// Maps use UCEB2 directly so the guest can populate Request StringMaps without
// constructing and then copying a duplicate DValue subtree.
static void wasm_request_envelope_append(String& envelope, const String& value)
{
u64 size = value.size();
while(size >= 0x80)
{
envelope.push_back((char)((size & 0x7f) | 0x80));
size >>= 7;
}
envelope.push_back((char)size);
envelope.append(value.data(), value.size());
}
static String wasm_encode_request_envelope(const Request& request, const String& entry_unit, const String& handler)
{
String envelope = "UCER";
envelope.push_back(1);
envelope.push_back(12);
wasm_request_envelope_append(envelope, ucb_encode(request.call));
wasm_request_envelope_append(envelope, ucb_encode_flat_string_map(request.params));
wasm_request_envelope_append(envelope, ucb_encode_flat_string_map(request.get));
wasm_request_envelope_append(envelope, ucb_encode_flat_string_map(request.post));
wasm_request_envelope_append(envelope, ucb_encode_flat_string_map(request.cookies));
wasm_request_envelope_append(envelope, ucb_encode_flat_string_map(request.session));
wasm_request_envelope_append(envelope, request.session_id);
wasm_request_envelope_append(envelope, request.session_name);
wasm_request_envelope_append(envelope, request.session_loaded_hash);
wasm_request_envelope_append(envelope, entry_unit);
wasm_request_envelope_append(envelope, request.in);
String websocket;
if(handler == "websocket")
{
DValue ws;
ws["connection_id"] = request.resources.websocket_connection_id;
ws["scope"] = request.resources.websocket_scope;
ws["opcode"] = (f64)request.resources.websocket_opcode;
ws["binary"].set_bool(request.resources.websocket_is_binary);
for(auto& id : request.resources.websocket_scope_connection_ids)
{
DValue value;
value = id;
ws["connections"].push(value);
}
ws["connection_state"] = request.connection;
websocket = ucb_encode(ws);
}
wasm_request_envelope_append(envelope, websocket);
return(envelope);
}
// ---- workspace (per request) ----------------------------------------------
class WasmWorkspace : public WasmRequestProfile
@@ -1524,7 +1576,7 @@ public:
return("");
}
String apply_context(const DValue& context_tree)
String apply_context(const Request& request, const String& entry_unit, const String& handler)
{
auto phase_start = std::chrono::steady_clock::now();
auto phase_us = [&]() -> u64 {
@@ -1533,7 +1585,7 @@ public:
phase_start = now;
return(elapsed);
};
String encoded = ucb_encode(context_tree);
String encoded = wasm_encode_request_envelope(request, entry_unit, handler);
server_config_bytes = worker.server_config_encoded.size();
context_bytes = server_config_bytes + encoded.size();
context_encode_us = phase_us();
@@ -3787,15 +3839,15 @@ inline String wasm_worker_prepare(WasmWorker& worker)
// ---- public entry: one request through one workspace -----------------------
inline WasmResponse wasm_worker_serve(WasmWorker& worker, const DValue& context_tree, const String& entry_source_path,
const String& handler = "render", const Request* request = 0)
inline WasmResponse wasm_worker_serve(WasmWorker& worker, const Request& request, const String& entry_source_path,
const String& handler = "render")
{
WasmResponse response;
f64 serve_started = time_precise();
auto workspace_start = std::chrono::steady_clock::now();
f64 cpu_started = wasm_thread_cpu_time();
struct rusage thread_runtime_start = {};
bool thread_runtime_profiled = request && worker.cfg.profile_thread_runtime && getrusage(RUSAGE_THREAD, &thread_runtime_start) == 0;
bool thread_runtime_profiled = worker.cfg.profile_thread_runtime && getrusage(RUSAGE_THREAD, &thread_runtime_start) == 0;
int thread_cpu_start = thread_runtime_profiled ? sched_getcpu() : -1;
WasmWorkspace workspace(worker);
f64 setup_cpu_finished = wasm_thread_cpu_time();
@@ -3803,17 +3855,14 @@ inline WasmResponse wasm_worker_serve(WasmWorker& worker, const DValue& context_
std::chrono::steady_clock::now() - workspace_start).count();
workspace.workspace_setup_cpu_us = cpu_started > 0 && setup_cpu_finished > cpu_started ?
(u64)((setup_cpu_finished - cpu_started) * 1000000.0) : 0;
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_params, request->stats.time_input, request->stats.time_start,
serve_started, cpu_started);
workspace.request_perf.thread_runtime_start = thread_runtime_start;
workspace.request_perf.thread_cpu_start = thread_cpu_start;
workspace.request_perf.thread_runtime_profiled = thread_runtime_profiled;
if(request->stats.time_start > 0 && serve_started > request->stats.time_start)
workspace.dispatch_us = (u64)((serve_started - request->stats.time_start) * 1000000.0);
}
workspace.set_perf_snapshot(my_pid, (u64)parent_pid, request.server ? request.server->request_count : 0,
request.stats.time_init, request.stats.time_params, request.stats.time_input, request.stats.time_start,
serve_started, cpu_started);
workspace.request_perf.thread_runtime_start = thread_runtime_start;
workspace.request_perf.thread_cpu_start = thread_cpu_start;
workspace.request_perf.thread_runtime_profiled = thread_runtime_profiled;
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();
f64 birth_cpu_start = wasm_thread_cpu_time();
String error = workspace.birth();
@@ -3826,7 +3875,7 @@ inline WasmResponse wasm_worker_serve(WasmWorker& worker, const DValue& context_
{
auto context_start = std::chrono::steady_clock::now();
f64 context_cpu_start = wasm_thread_cpu_time();
error = workspace.apply_context(context_tree);
error = workspace.apply_context(request, entry_source_path, handler);
f64 context_cpu_finished = wasm_thread_cpu_time();
workspace.context_apply_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - context_start).count();