Profile bounded hostcall operations

This commit is contained in:
udo
2026-07-17 00:01:19 +00:00
parent e9644c717f
commit 7789385ef5
2 changed files with 63 additions and 7 deletions
+47 -5
View File
@@ -154,6 +154,7 @@ struct WasmUnitModuleOperation
struct WasmRequestProfile
{
static const u64 HOSTCALL_OPERATION_MAX = 96;
u64 dispatch_us = 0;
u64 workspace_setup_us = 0;
u64 workspace_birth_us = 0;
@@ -186,6 +187,9 @@ struct WasmRequestProfile
u64 unit_initialize_total_us = 0;
u64 hostcall_count = 0;
u64 hostcall_total_us = 0;
u64 hostcall_operation_slots = 0;
u64 hostcall_operation_counts[HOSTCALL_OPERATION_MAX] = {};
u64 hostcall_operation_us[HOSTCALL_OPERATION_MAX] = {};
u64 mysql_hostcall_count = 0;
u64 mysql_hostcall_total_us = 0;
u64 mysql_operation_count = 0;
@@ -1080,6 +1084,8 @@ public:
}
private:
friend class WasmWorkspace;
static String cached_wasm_path(const String& wasm_path)
{
if(wasm_path.size() >= 5 && wasm_path.rfind(".wasm", wasm_path.size() - 5) == wasm_path.size() - 5)
@@ -1169,6 +1175,7 @@ private:
}
std::map<String, std::shared_ptr<WasmUnitModule>> module_cache;
std::vector<String> hostcall_operation_names;
};
// ---- workspace (per request) ----------------------------------------------
@@ -2172,8 +2179,17 @@ private:
WasmWorkspace* self = this;
auto add = [&](auto&& callback) -> Extern {
String profile_name = name;
auto profiled = [self, callback, profile_name](Caller caller, Span<const Val> args, Span<Val> results) mutable -> Result<std::monostate, Trap> {
u64 profile_index = self->hostcall_operation_slots;
if(profile_index < WasmRequestProfile::HOSTCALL_OPERATION_MAX)
{
self->hostcall_operation_slots++;
if(self->worker.hostcall_operation_names.size() <= profile_index)
self->worker.hostcall_operation_names.push_back(name);
}
bool profile_enabled = name != "uce_host_request_perf";
bool profile_mysql = name == "uce_host_mysql";
bool profile_memcache = name == "uce_host_memcache_command";
auto profiled = [self, callback, profile_index, profile_enabled, profile_mysql, profile_memcache](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);
// Epoch interruption limits guest CPU, not time spent in native I/O,
@@ -2181,17 +2197,22 @@ private:
// membrane every hostcall crosses so newly added blocking imports
// cannot silently consume the next guest segment's budget.
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
if(profile_name != "uce_host_request_perf")
if(profile_enabled)
{
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")
if(profile_index < WasmRequestProfile::HOSTCALL_OPERATION_MAX)
{
self->hostcall_operation_counts[profile_index]++;
self->hostcall_operation_us[profile_index] += elapsed;
}
if(profile_mysql)
{
self->mysql_hostcall_count++;
self->mysql_hostcall_total_us += elapsed;
}
else if(profile_name == "uce_host_memcache_command")
else if(profile_memcache)
{
self->memcache_hostcall_count++;
self->memcache_hostcall_total_us += elapsed;
@@ -2263,6 +2284,27 @@ private:
response["context_apply_us"] = (f64)self->context_apply_us;
response["hostcall_count"] = (f64)self->hostcall_count;
response["hostcall_us"] = (f64)self->hostcall_total_us;
std::vector<u64> invoked_hostcalls;
for(u64 i = 0; i < self->hostcall_operation_slots; i++)
if(self->hostcall_operation_counts[i] > 0)
invoked_hostcalls.push_back(i);
std::sort(invoked_hostcalls.begin(), invoked_hostcalls.end(), [&](u64 a, u64 b) {
if(self->hostcall_operation_us[a] != self->hostcall_operation_us[b])
return(self->hostcall_operation_us[a] > self->hostcall_operation_us[b]);
return(self->worker.hostcall_operation_names[a] < self->worker.hostcall_operation_names[b]);
});
response["hostcall_operations_dropped"] = (f64)(invoked_hostcalls.size() > 32 ? invoked_hostcalls.size() - 32 : 0);
response["hostcall_operations"].set_array();
for(u64 i = 0; i < invoked_hostcalls.size() && i < 32; i++)
{
u64 operation_index = invoked_hostcalls[i];
String& operation_name = self->worker.hostcall_operation_names[operation_index];
DValue item;
item["name"] = operation_name.rfind("uce_host_", 0) == 0 ? operation_name.substr(9) : operation_name;
item["count"] = (f64)self->hostcall_operation_counts[operation_index];
item["us"] = (f64)self->hostcall_operation_us[operation_index];
response["hostcall_operations"].push(item);
}
response["mysql_hostcall_count"] = (f64)self->mysql_hostcall_count;
response["mysql_hostcall_us"] = (f64)self->mysql_hostcall_total_us;
response["mysql_operation_count"] = (f64)self->mysql_operation_count;