Attribute per-unit load phases accurately

This commit is contained in:
root
2026-07-17 01:41:33 +00:00
parent 51cbb19f7d
commit aeab8df208
3 changed files with 51 additions and 12 deletions
+45 -10
View File
@@ -150,6 +150,12 @@ struct WasmUnitModuleOperation
u64 parse_us = 0;
u64 build_us = 0;
u64 classify_us = 0;
u64 allocate_us = 0;
u64 import_us = 0;
u64 symbol_resolve_count = 0;
u64 symbol_resolve_us = 0;
u64 instantiate_us = 0;
u64 initialize_us = 0;
};
struct WasmRequestProfile
@@ -1642,7 +1648,8 @@ private:
unit_module_parse_total_us += module_profile.parse_us;
unit_module_compile_total_us += module_profile.compile_us;
unit_module_classify_total_us += module_profile.classify_us;
if(unit_module_operations.size() < 32)
size_t module_operation_index = unit_module_operations.size();
if(module_operation_index < 32)
{
String unit_name = source_path;
String site_prefix = worker.cfg.site_root;
@@ -1665,7 +1672,10 @@ private:
unit_module_operations.push_back(operation);
}
else
{
module_operation_index = 32;
unit_module_operations_dropped++;
}
if(!mod)
return(error);
// Compiling/deserializing a cold module is host work. Refresh the guest
@@ -1693,11 +1703,16 @@ private:
if(mod->dylink.table_size > table->size(cx) - table_next_free)
return("funcref table headroom exhausted by " + source_path);
table_next_free += mod->dylink.table_size;
unit_allocate_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
u64 allocate_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - allocate_start).count();
unit_allocate_total_us += allocate_us;
if(module_operation_index < unit_module_operations.size())
unit_module_operations[module_operation_index].allocate_us = allocate_us;
// import resolution
auto import_start = std::chrono::steady_clock::now();
u64 symbol_resolve_count_start = unit_symbol_resolve_count;
u64 symbol_resolve_us_start = unit_symbol_resolve_total_us;
std::vector<wasmtime::Extern> imports;
imports.reserve(mod->imports.size());
std::vector<std::pair<String, wasmtime::Global>> deferred_got;
@@ -1793,13 +1808,24 @@ private:
continue;
}
}
unit_import_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
u64 import_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - import_start).count();
unit_import_total_us += import_us;
if(module_operation_index < unit_module_operations.size())
{
auto& operation = unit_module_operations[module_operation_index];
operation.import_us = import_us;
operation.symbol_resolve_count = unit_symbol_resolve_count - symbol_resolve_count_start;
operation.symbol_resolve_us = unit_symbol_resolve_total_us - symbol_resolve_us_start;
}
auto instantiate_start = std::chrono::steady_clock::now();
auto created = wasmtime::Instance::create(cx, module, imports);
unit_instantiate_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
u64 instantiate_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - instantiate_start).count();
unit_instantiate_total_us += instantiate_us;
if(module_operation_index < unit_module_operations.size())
unit_module_operations[module_operation_index].instantiate_us = instantiate_us;
if(!created)
return(source_path + ": instantiation failed: " + trap_text(created.err()));
@@ -1848,8 +1874,11 @@ private:
if(worker.cfg.verbose)
fprintf(stderr, "[wasm] loaded %s (mem_base=%u table_base=%u)\n",
source_path.c_str(), memory_base, table_base);
unit_initialize_total_us += (u64)std::chrono::duration_cast<std::chrono::microseconds>(
u64 initialize_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - initialize_start).count();
unit_initialize_total_us += initialize_us;
if(module_operation_index < unit_module_operations.size())
unit_module_operations[module_operation_index].initialize_us = initialize_us;
// Exclude the rest of host-side loading as well. A genuine runaway loop
// makes no loads, so it still trips the deadline.
ctx().set_epoch_deadline(worker.cfg.epoch_deadline_ticks);
@@ -2278,8 +2307,8 @@ private:
DValue response;
if(self->request_perf.active)
{
f64 now = time_precise();
f64 cpu_now = wasm_thread_cpu_time();
f64 now = time_precise();
response["worker_pid"] = (f64)self->request_perf.worker_pid;
response["parent_pid"] = (f64)self->request_perf.parent_pid;
response["request_count"] = (f64)self->request_perf.request_count;
@@ -2383,6 +2412,12 @@ private:
item["parse_us"] = (f64)operation.parse_us;
item["build_us"] = (f64)operation.build_us;
item["classify_us"] = (f64)operation.classify_us;
item["allocate_us"] = (f64)operation.allocate_us;
item["import_us"] = (f64)operation.import_us;
item["symbol_resolve_count"] = (f64)operation.symbol_resolve_count;
item["symbol_resolve_us"] = (f64)operation.symbol_resolve_us;
item["instantiate_us"] = (f64)operation.instantiate_us;
item["initialize_us"] = (f64)operation.initialize_us;
response["unit_module_operations"].push(item);
}
response["unit_allocate_us"] = (f64)self->unit_allocate_total_us;
@@ -3455,12 +3490,12 @@ inline WasmResponse wasm_worker_serve(WasmWorker& worker, const DValue& context_
{
WasmResponse response;
f64 serve_started = time_precise();
f64 cpu_started = wasm_thread_cpu_time();
auto workspace_start = std::chrono::steady_clock::now();
f64 cpu_started = wasm_thread_cpu_time();
WasmWorkspace workspace(worker);
f64 setup_cpu_finished = wasm_thread_cpu_time();
workspace.workspace_setup_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - workspace_start).count();
f64 setup_cpu_finished = wasm_thread_cpu_time();
workspace.workspace_setup_cpu_us = cpu_started > 0 && setup_cpu_finished > cpu_started ?
(u64)((setup_cpu_finished - cpu_started) * 1000000.0) : 0;
if(request)
@@ -3474,9 +3509,9 @@ inline WasmResponse wasm_worker_serve(WasmWorker& worker, const DValue& context_
auto birth_start = std::chrono::steady_clock::now();
f64 birth_cpu_start = wasm_thread_cpu_time();
String error = workspace.birth();
f64 birth_cpu_finished = wasm_thread_cpu_time();
workspace.workspace_birth_us = (u64)std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - birth_start).count();
f64 birth_cpu_finished = wasm_thread_cpu_time();
workspace.workspace_birth_cpu_us = birth_cpu_start > 0 && birth_cpu_finished > birth_cpu_start ?
(u64)((birth_cpu_finished - birth_cpu_start) * 1000000.0) : 0;
if(error == "")
@@ -3484,9 +3519,9 @@ 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);
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();
f64 context_cpu_finished = wasm_thread_cpu_time();
workspace.context_apply_cpu_us = context_cpu_start > 0 && context_cpu_finished > context_cpu_start ?
(u64)((context_cpu_finished - context_cpu_start) * 1000000.0) : 0;
}