diff --git a/site/demo/index.uce b/site/demo/index.uce
index 3a9fa4c..9b68240 100644
--- a/site/demo/index.uce
+++ b/site/demo/index.uce
@@ -84,10 +84,16 @@ RENDER(Request& context)
System Info
- print("Worker PID: ", my_pid, "\n");
- print("Parent PID: ", parent_pid, "\n");
+ DValue perf = request_perf();
+ print("Worker PID: ", (u64)perf["worker_pid"].to_u64(), "\n");
+ print("Parent PID: ", (u64)perf["parent_pid"].to_u64(), "\n");
+ print("Request #: ", (u64)perf["request_count"].to_u64(), "\n");
+ print("Accept us: ", (f64)perf["accept_us"].to_f64(), "\n");
+ print("Running us: ", (f64)perf["running_us"].to_f64(), "\n");
+ print("Total us: ", (f64)perf["total_us"].to_f64(), "\n");
+ if(perf["workspace_birth_us"].type != 'S')
+ print("Workspace birth us: ", (u64)perf["workspace_birth_us"].to_u64(), "\n");
print("Output buffer size: ", context.ob->str().length(), "\n");
- print("Request #", context.server->request_count, "\n");
?>
} ?>
diff --git a/src/lib/sys.cpp b/src/lib/sys.cpp
index 8ac6e3e..dbf6da8 100644
--- a/src/lib/sys.cpp
+++ b/src/lib/sys.cpp
@@ -33,6 +33,7 @@ int uce_host_server_start_http(const char* key, size_t key_len, const char* bind
int uce_host_server_stop(const char* key, size_t key_len);
size_t uce_host_memcache_command(uint64_t sockfd, const char* command, size_t command_len, char* buf, size_t cap);
size_t uce_host_mysql(const char* in, size_t in_len, char* out, size_t cap);
+size_t uce_host_request_perf(const char* in, size_t in_len, char* out, size_t cap);
}
static String wasm_current_unit_file()
@@ -117,6 +118,22 @@ bool config_map_bool(StringMap& cfg, String key, bool fallback) { return(config_
u64 config_u64(String key, u64 fallback) { return(context ? config_map_u64(context->server->config, key, fallback) : fallback); }
f64 config_f64(String key, f64 fallback) { return(context ? config_map_f64(context->server->config, key, fallback) : fallback); }
bool config_bool(String key, bool fallback) { return(context ? config_map_bool(context->server->config, key, fallback) : fallback); }
+DValue request_perf()
+{
+ size_t required = uce_host_request_perf("", 0, 0, 0);
+ if(required == 0)
+ return(DValue());
+ String encoded_response(required, 0);
+ size_t got = uce_host_request_perf("", 0, &encoded_response[0], required);
+ if(got == 0 || got > required)
+ return(DValue());
+ DValue response;
+ String decode_error;
+ if(ucb_decode(encoded_response, response, &decode_error))
+ return(response);
+ return(DValue());
+}
+
f64 time_precise() { return(uce_host_time_precise()); }
u64 time() { return(uce_host_time()); }
// The native build shells out to `date`; the wasm core has no shell, so it
diff --git a/src/lib/sys.h b/src/lib/sys.h
index e9863b8..9ba2268 100644
--- a/src/lib/sys.h
+++ b/src/lib/sys.h
@@ -67,6 +67,11 @@ bool config_bool(String key, bool fallback = true);
f64 time_precise();
u64 time();
String time_format_local(String format = "", u64 timestamp = 0);
+
+// Runtime timing/profiling snapshot for the active wasm request/workspace.
+struct DValue;
+DValue request_perf();
+
String time_format_utc(String format = "", u64 timestamp = 0);
String time_format_relative(u64 timestamp, String format_very_recent = "", u64 medium_recency_seconds = 0, String format_medium_recent = "", u64 not_recent_seconds = 0, String format_not_recent = "");
u64 time_parse(String time_String);
diff --git a/src/linux_fastcgi.cpp b/src/linux_fastcgi.cpp
index a5309d6..6f58cbb 100644
--- a/src/linux_fastcgi.cpp
+++ b/src/linux_fastcgi.cpp
@@ -459,13 +459,15 @@ int handle_cli_complete(FastCGIRequest& request)
}
int handle_request(FastCGIRequest& request) {
- // This is always the first event to occur. It occurs when the
- // server receives all parameters. There may be more data coming on the
- // standard input stream.
- if (request.params.count("REQUEST_URI"))
- return 0; // OK, continue processing
- else
- return 1; // stop processing and return error code
+ // This is always the first event to occur. It occurs when the
+ // server receives all parameters. There may be more data coming on the
+ // standard input stream.
+ if(request.stats.time_init == 0)
+ request.stats.time_init = time_precise();
+ if(request.params.count("REQUEST_URI"))
+ return(0); // OK, continue processing
+ else
+ return(1); // stop processing and return error code
}
int handle_data(FastCGIRequest& request) {
@@ -478,6 +480,8 @@ int handle_complete(FastCGIRequest& request) {
Request* previous_context = set_active_request(request);
server_state.request_count += 1;
request.server = &server_state;
+ if(request.stats.time_init == 0)
+ request.stats.time_init = time_precise();
request.stats.time_start = time_precise();
//request.stats.mem_alloc = 0;
//request.stats.mem_high = 0;
diff --git a/src/wasm/backend.cpp b/src/wasm/backend.cpp
index f9729a8..78c3548 100644
--- a/src/wasm/backend.cpp
+++ b/src/wasm/backend.cpp
@@ -147,7 +147,7 @@ String wasm_backend_serve(Request& request, const String& entry_unit, const Stri
ctx["ws"]["connection_state"] = request.connection;
}
- WasmResponse response = wasm_worker_serve(*g_wasm_worker, ctx, entry_unit, handler);
+ WasmResponse response = wasm_worker_serve(*g_wasm_worker, ctx, entry_unit, handler, &request);
if(!response.ok)
return(response.error == "" ? String("wasm workspace failed") : response.error);
diff --git a/src/wasm/core_hostcalls.syms b/src/wasm/core_hostcalls.syms
index ae9c68b..86d0ed6 100644
--- a/src/wasm/core_hostcalls.syms
+++ b/src/wasm/core_hostcalls.syms
@@ -18,6 +18,7 @@ uce_host_mysql
uce_host_zip
uce_host_units
uce_host_component_resolve
+uce_host_request_perf
uce_host_file_exists
uce_host_file_read
uce_host_file_write
diff --git a/src/wasm/worker.cpp b/src/wasm/worker.cpp
index 0478472..f4ebc91 100644
--- a/src/wasm/worker.cpp
+++ b/src/wasm/worker.cpp
@@ -404,10 +404,30 @@ public:
u64 component_resolve_count = 0;
u64 component_resolve_total_us = 0;
+ struct RequestPerfSnapshot
+ {
+ u64 worker_pid = 0;
+ u64 parent_pid = 0;
+ u64 request_count = 0;
+ f64 time_init = 0;
+ f64 time_start = 0;
+ bool active = false;
+ } request_perf;
+
explicit WasmWorkspace(WasmWorker& w) : worker(w), store(w.engine)
{
}
+ void set_perf_snapshot(u64 worker_pid, u64 parent_pid, u64 request_count, f64 time_init, f64 time_start)
+ {
+ request_perf.worker_pid = worker_pid;
+ request_perf.parent_pid = parent_pid;
+ request_perf.request_count = request_count;
+ request_perf.time_init = time_init;
+ request_perf.time_start = time_start;
+ request_perf.active = true;
+ }
+
#ifdef UCE_WASM_HOST_CONNECTORS
// Host-owned resource handle table (ยง3.1): connections opened by the guest
// live here and are closed when the workspace drops at request end.
@@ -1221,9 +1241,33 @@ private:
}));
if(mod == "env" && name == "uce_host_time_precise")
return(add([](Caller, Span