Buffer Wasm metadata reads
This commit is contained in:
@@ -243,8 +243,12 @@ check. Exact repeated load paths are then deduplicated before canonicalization,
|
||||
while distinct aliases are resolved independently so symlink retargets remain
|
||||
visible by the next hard validation.
|
||||
When a current serialized module exists, the worker scans wasm section headers
|
||||
and reads only `dylink.0`, `uce.abi`, and the tiny `uce.module` identity; it does
|
||||
not fault the code and data bodies into every new worker. A missing/stale/invalid serialized module
|
||||
through a bounded 4 KiB positional buffer and retains only `dylink.0`, `uce.abi`,
|
||||
and the tiny `uce.module` identity. It skips code and data bodies rather than
|
||||
issuing byte-at-a-time reads or faulting those bodies into every new worker.
|
||||
The request profile reports the physical read-ahead bytes and positional read
|
||||
count. Initial and final descriptor identity checks reject an artifact changed
|
||||
during the scan. A missing/stale/invalid serialized module
|
||||
still reads, validates, compiles, and republishes the complete wasm artifact.
|
||||
The proactive compiler also creates that serialization immediately after source
|
||||
compilation, keeping first-worker native compilation off the request path.
|
||||
|
||||
@@ -84,6 +84,7 @@ if [[ "$action" == "run" ]]; then
|
||||
scripts/test_component_resolution_ttl.sh
|
||||
timeout --signal=TERM --kill-after=5s 120s scripts/test_entry_freshness_ttl.sh
|
||||
scripts/test_unit_export_surface.sh
|
||||
timeout --signal=TERM --kill-after=5s 120s scripts/test_wasm_metadata_buffer.sh
|
||||
scripts/test_wasm_source_locations.sh
|
||||
scripts/test_socket_activation.sh
|
||||
fi
|
||||
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
test_name="wasm-metadata-buffer-test-$$"
|
||||
site_directory="${UCE_TEST_SITE_DIRECTORY:-site}"
|
||||
bin_directory="${UCE_TEST_BIN_DIRECTORY:-/tmp/uce/work}"
|
||||
if [[ -r /etc/uce/settings.cfg ]]; then
|
||||
if [[ -z "${UCE_TEST_SITE_DIRECTORY:-}" ]]; then
|
||||
configured_site_directory=$(awk -F= '/^[[:space:]]*HTTP_DOCUMENT_ROOT[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2; exit}' /etc/uce/settings.cfg)
|
||||
site_directory="${configured_site_directory:-$site_directory}"
|
||||
fi
|
||||
if [[ -z "${UCE_TEST_BIN_DIRECTORY:-}" ]]; then
|
||||
configured_bin_directory=$(awk -F= '/^[[:space:]]*BIN_DIRECTORY[[:space:]]*=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2); print $2; exit}' /etc/uce/settings.cfg)
|
||||
bin_directory="${configured_bin_directory:-$bin_directory}"
|
||||
fi
|
||||
fi
|
||||
source_dir="$site_directory/$test_name"
|
||||
artifact_dir=""
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$source_dir"
|
||||
if [[ -n "$artifact_dir" ]]; then
|
||||
rm -rf "$artifact_dir"
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
mkdir -p "$source_dir"
|
||||
artifact_dir="$(scripts/unit_cache_directory "$bin_directory")$(realpath "$source_dir")"
|
||||
|
||||
printf '%s\n' \
|
||||
'CLI(Request& context) {' \
|
||||
' String target = context.get["unit"];' \
|
||||
' String rendered = component(target, context);' \
|
||||
' DValue perf = request_perf();' \
|
||||
' DValue selected;' \
|
||||
' perf["unit_module_operations"].each([&](DValue operation, String key) {' \
|
||||
' if(operation["kind"].to_string() == "component" && contains(operation["unit"].to_string(), target + ".uce")) selected = operation;' \
|
||||
' });' \
|
||||
' print(rendered, "\t", selected["source"].to_string(), "\t", selected["read_count"].to_string(), "\t", selected["read_bytes"].to_string(), "\t", selected["read_us"].to_string());' \
|
||||
'}' >"$source_dir/parent.uce"
|
||||
|
||||
payload=$(head -c 131072 /dev/zero | tr '\0' x)
|
||||
for unit in $(seq 0 7); do
|
||||
printf 'String metadata_payload_%s() { return("%s"); }\nCOMPONENT(Request& context) { String payload = metadata_payload_%s(); u64 offset = std::atoi(context.get["offset"].c_str()) %% payload.size(); print(std::to_string(payload.size()), ":", payload.substr(offset, 1)); }\n' \
|
||||
"$unit" "$payload" "$unit" >"$source_dir/component-$unit.uce"
|
||||
done
|
||||
unset payload
|
||||
|
||||
declare -a read_times=()
|
||||
for unit in $(seq 0 7); do
|
||||
found=0
|
||||
for attempt in $(seq 1 20); do
|
||||
output=$(timeout --signal=TERM --kill-after=2s 30s scripts/uce-cli "/$test_name/parent.uce?unit=component-$unit&offset=$attempt")
|
||||
IFS=$'\t' read -r marker source read_count read_bytes read_us <<<"$output"
|
||||
if [[ "$marker" != "131072:x" ]]; then
|
||||
echo "metadata buffer component failed: unit=$unit output=$output" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$source" != "serialized" ]]; then
|
||||
continue
|
||||
fi
|
||||
wasm_size=$(stat -c %s "$artifact_dir/component-$unit.uce.wasm")
|
||||
if ! awk -v count="$read_count" -v bytes="$read_bytes" -v size="$wasm_size" \
|
||||
'BEGIN { exit !(count > 0 && count <= 64 && bytes > 0 && bytes <= count * 4096 && bytes < size) }'; then
|
||||
echo "metadata buffer read was not bounded: unit=$unit reads=$read_count bytes=$read_bytes wasm=$wasm_size us=$read_us" >&2
|
||||
exit 1
|
||||
fi
|
||||
read_times+=("$read_us")
|
||||
found=1
|
||||
break
|
||||
done
|
||||
if (( found == 0 )); then
|
||||
echo "metadata buffer did not observe a serialized cold-worker load for component-$unit" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
mapfile -t sorted < <(printf '%s\n' "${read_times[@]}" | sort -n)
|
||||
median=${sorted[$(( ${#sorted[@]} / 2 ))]}
|
||||
maximum=${sorted[$(( ${#sorted[@]} - 1 ))]}
|
||||
if ! awk -v median="$median" 'BEGIN { exit !(median < 3000) }'; then
|
||||
echo "metadata buffer median exceeded 3ms: median=${median}us maximum=${maximum}us samples=${read_times[*]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "wasm metadata buffer passed: ${#read_times[@]} cold serialized loads, median ${median}us, maximum ${maximum}us"
|
||||
@@ -19,7 +19,7 @@ Entry readiness reports inclusive `ready_freshness_us` plus `ready_source_genera
|
||||
|
||||
Successful first loads within the request are counted by `unit_load_count` and divided into `unit_module_us`, `unit_allocate_us`, `unit_import_us`, `unit_instantiate_us`, and `unit_initialize_us`. These cover compiled-module lookup, guest memory/table allocation, import construction, Wasmtime instantiation, and relocations/constructors/request binding. `entry_unit_load_count` and `entry_unit_materialize_us` isolate the initial page/CLI unit; `dynamic_include_load_count` and `dynamic_include_materialize_us` isolate side units first requested through `component()`. The per-unit bounded list adds `kind` (`entry` or `component`) and `materialize_us`, the inclusive host-side time from module acquisition through request binding. Repeated handlers from an already loaded unit are excluded.
|
||||
|
||||
`unit_module_cache_hit_count` and `unit_module_cache_miss_count` divide module loads by the worker's compiled-module cache. A miss is further identified by `unit_module_serialized_cache_hit_count` when Wasmtime deserializes the current `.cwasm`; `unit_module_compile_count` means it fell back to compiling the `.wasm`. `unit_module_lookup_us`, `unit_module_read_us`, `unit_module_read_bytes`, `unit_module_parse_us`, `unit_module_compile_us`, and `unit_module_classify_us` divide `unit_module_us` into artifact stat/cache lookup, wasm metadata/full-artifact read volume, custom-section parse, deserialize-or-compile, and immutable import classification. A current serialized-module hit scans only section headers and the `dylink.0`/`uce.abi` payloads; compilation fallback reads the complete wasm. The phase sum can be below the total because allocation and cache publication overhead remain in the aggregate.
|
||||
`unit_module_cache_hit_count` and `unit_module_cache_miss_count` divide module loads by the worker's compiled-module cache. A miss is further identified by `unit_module_serialized_cache_hit_count` when Wasmtime deserializes the current `.cwasm`; `unit_module_compile_count` means it fell back to compiling the `.wasm`. `unit_module_lookup_us`, `unit_module_read_us`, `unit_module_read_bytes`, `unit_module_read_count`, `unit_module_parse_us`, `unit_module_compile_us`, and `unit_module_classify_us` divide `unit_module_us` into artifact stat/cache lookup, wasm metadata/full-artifact read volume, positional metadata reads, custom-section parse, deserialize-or-compile, and immutable import classification. Per-unit `unit_module_operations` expose the same `read_count`. On a serialized-module hit, `read_bytes` is the physical bounded read-ahead volume rather than only the logical selected bytes. The scanner skips code/data bodies and retains only section headers plus `dylink.0`, `uce.abi`, and `uce.module`; compilation fallback reads the complete wasm and does not use positional metadata reads. The phase sum can be below the total because allocation and cache publication overhead remain in the aggregate.
|
||||
|
||||
`unit_symbol_resolve_count` and `unit_symbol_resolve_us` isolate function and data symbol lookup within `unit_import_us`. The remainder of import time covers import-vector construction, Wasmtime Globals, GOT function table placement, and related bindings.
|
||||
|
||||
|
||||
+2
-2
@@ -161,9 +161,9 @@ RENDER(Request& context)
|
||||
bool serialized_reads_bounded = module_misses == 0 || serialized_hits != module_misses || (module_read_bytes > 0 && module_read_bytes < module_misses * 1024 * 1024);
|
||||
bool unit_operation_profile_valid = true;
|
||||
perf["unit_module_operations"].each([&](DValue operation, String key) {
|
||||
unit_operation_profile_valid = unit_operation_profile_valid && operation["unit"].to_string() != "" && operation["allocate_us"].type != 'S' && operation["import_us"].type != 'S' && operation["symbol_resolve_count"].type != 'S' && operation["symbol_resolve_us"].type != 'S' && operation["instantiate_us"].type != 'S' && operation["initialize_us"].type != 'S';
|
||||
unit_operation_profile_valid = unit_operation_profile_valid && operation["unit"].to_string() != "" && operation["read_count"].type != 'S' && operation["allocate_us"].type != 'S' && operation["import_us"].type != 'S' && operation["symbol_resolve_count"].type != 'S' && operation["symbol_resolve_us"].type != 'S' && operation["instantiate_us"].type != 'S' && operation["initialize_us"].type != 'S';
|
||||
});
|
||||
bool unit_module_profile_valid = serialized_reads_bounded && unit_operation_profile_valid && perf["unit_module_cache_hit_count"].to_u64() + module_misses == perf["unit_load_count"].to_u64() && serialized_hits + perf["unit_module_compile_count"].to_u64() == module_misses && perf["unit_module_lookup_us"].type != 'S' && perf["unit_module_read_us"].type != 'S' && perf["unit_module_read_bytes"].type != 'S' && perf["unit_module_parse_us"].type != 'S' && perf["unit_module_compile_us"].type != 'S' && perf["unit_module_classify_us"].type != 'S';
|
||||
bool unit_module_profile_valid = serialized_reads_bounded && unit_operation_profile_valid && perf["unit_module_cache_hit_count"].to_u64() + module_misses == perf["unit_load_count"].to_u64() && serialized_hits + perf["unit_module_compile_count"].to_u64() == module_misses && perf["unit_module_lookup_us"].type != 'S' && perf["unit_module_read_us"].type != 'S' && perf["unit_module_read_bytes"].type != 'S' && perf["unit_module_read_count"].type != 'S' && perf["unit_module_parse_us"].type != 'S' && perf["unit_module_compile_us"].type != 'S' && perf["unit_module_classify_us"].type != 'S';
|
||||
bool transport_profile_valid = perf["transport_params_us"].type != 'S' && perf["transport_input_us"].type != 'S' && perf["handler_queue_us"].type != 'S' && perf["accept_us"].to_f64() + 2 >= perf["transport_params_us"].to_f64() + perf["transport_input_us"].to_f64() + perf["handler_queue_us"].to_f64();
|
||||
u64 phase_cpu_us = perf["workspace_setup_cpu_us"].to_u64() + perf["workspace_birth_cpu_us"].to_u64() + perf["context_apply_cpu_us"].to_u64();
|
||||
u64 birth_profile_us = perf["birth_policy_us"].to_u64() + perf["birth_import_us"].to_u64() + perf["birth_instantiate_us"].to_u64() + perf["birth_exports_us"].to_u64() + perf["birth_initialize_us"].to_u64();
|
||||
|
||||
+85
-35
@@ -126,6 +126,7 @@ struct WasmUnitModuleLoadProfile
|
||||
u64 lookup_us = 0;
|
||||
u64 read_us = 0;
|
||||
u64 read_bytes = 0;
|
||||
u64 read_count = 0;
|
||||
u64 parse_us = 0;
|
||||
u64 compile_us = 0;
|
||||
u64 classify_us = 0;
|
||||
@@ -177,6 +178,7 @@ struct WasmUnitModuleOperation
|
||||
u64 lookup_us = 0;
|
||||
u64 read_us = 0;
|
||||
u64 read_bytes = 0;
|
||||
u64 read_count = 0;
|
||||
u64 parse_us = 0;
|
||||
u64 build_us = 0;
|
||||
u64 classify_us = 0;
|
||||
@@ -237,6 +239,7 @@ struct WasmRequestProfile
|
||||
u64 unit_module_lookup_total_us = 0;
|
||||
u64 unit_module_read_total_us = 0;
|
||||
u64 unit_module_read_bytes = 0;
|
||||
u64 unit_module_read_count = 0;
|
||||
u64 unit_module_parse_total_us = 0;
|
||||
u64 unit_module_compile_total_us = 0;
|
||||
u64 unit_module_classify_total_us = 0;
|
||||
@@ -893,38 +896,67 @@ static String wasm_source_map_lookup(const WasmSourceMap& map, u64 address)
|
||||
return(result);
|
||||
}
|
||||
|
||||
static bool wasm_pread_all(int fd, u64 offset, u8* out, size_t size, u64& bytes_read)
|
||||
struct WasmMetadataReader
|
||||
{
|
||||
size_t done = 0;
|
||||
while(done < size)
|
||||
{
|
||||
ssize_t n = pread(fd, out + done, size - done, (off_t)(offset + done));
|
||||
if(n < 0 && errno == EINTR)
|
||||
continue;
|
||||
if(n <= 0)
|
||||
return(false);
|
||||
done += (size_t)n;
|
||||
bytes_read += (u64)n;
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
int fd = -1;
|
||||
u64 file_size = 0;
|
||||
u64 bytes_read = 0;
|
||||
u64 read_count = 0;
|
||||
u64 buffer_offset = 0;
|
||||
size_t buffer_size = 0;
|
||||
u8 buffer[4096];
|
||||
|
||||
static bool wasm_read_uleb_fd(int fd, u64& pos, u64 end, u64& out, u64& bytes_read)
|
||||
{
|
||||
out = 0;
|
||||
u32 shift = 0;
|
||||
while(pos < end && shift < 64)
|
||||
bool read(u64 offset, u8* out, size_t size)
|
||||
{
|
||||
u8 byte = 0;
|
||||
if(!wasm_pread_all(fd, pos++, &byte, 1, bytes_read))
|
||||
if(offset > file_size || size > file_size - offset)
|
||||
return(false);
|
||||
out |= ((u64)(byte & 0x7f)) << shift;
|
||||
if((byte & 0x80) == 0)
|
||||
return(true);
|
||||
shift += 7;
|
||||
while(size > 0)
|
||||
{
|
||||
if(offset < buffer_offset || offset >= buffer_offset + buffer_size)
|
||||
{
|
||||
buffer_offset = offset;
|
||||
buffer_size = 0;
|
||||
size_t wanted = (size_t)std::min<u64>(sizeof(buffer), file_size - offset);
|
||||
while(true)
|
||||
{
|
||||
ssize_t count = pread(fd, buffer, wanted, (off_t)offset);
|
||||
if(count < 0 && errno == EINTR)
|
||||
continue;
|
||||
if(count <= 0)
|
||||
return(false);
|
||||
buffer_size = (size_t)count;
|
||||
bytes_read += (u64)count;
|
||||
read_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t available = buffer_size - (size_t)(offset - buffer_offset);
|
||||
size_t copied = std::min(size, available);
|
||||
memcpy(out, buffer + (size_t)(offset - buffer_offset), copied);
|
||||
offset += copied;
|
||||
out += copied;
|
||||
size -= copied;
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
bool read_uleb(u64& pos, u64 end, u64& out)
|
||||
{
|
||||
out = 0;
|
||||
u32 shift = 0;
|
||||
while(pos < end && shift < 64)
|
||||
{
|
||||
u8 byte = 0;
|
||||
if(!read(pos++, &byte, 1))
|
||||
return(false);
|
||||
out |= ((u64)(byte & 0x7f)) << shift;
|
||||
if((byte & 0x80) == 0)
|
||||
return(true);
|
||||
shift += 7;
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
};
|
||||
|
||||
static void wasm_write_uleb(std::vector<u8>& out, u64 value)
|
||||
{
|
||||
@@ -937,10 +969,11 @@ static void wasm_write_uleb(std::vector<u8>& out, u64 value)
|
||||
while(value);
|
||||
}
|
||||
|
||||
static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadata, String& error, u64& bytes_read,
|
||||
static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadata, String& error, u64& bytes_read, u64& read_count,
|
||||
u64 expected_modified_ns, u64 expected_changed_ns, u64 expected_size)
|
||||
{
|
||||
bytes_read = 0;
|
||||
read_count = 0;
|
||||
int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if(fd < 0)
|
||||
return(false);
|
||||
@@ -960,9 +993,14 @@ static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadat
|
||||
return(false);
|
||||
}
|
||||
u64 file_size = (u64)st.st_size;
|
||||
WasmMetadataReader reader;
|
||||
reader.fd = fd;
|
||||
reader.file_size = file_size;
|
||||
u8 header[8];
|
||||
if(!wasm_pread_all(fd, 0, header, sizeof(header), bytes_read) || memcmp(header, "\0asm\1\0\0\0", sizeof(header)) != 0)
|
||||
if(!reader.read(0, header, sizeof(header)) || memcmp(header, "\0asm\1\0\0\0", sizeof(header)) != 0)
|
||||
{
|
||||
bytes_read = reader.bytes_read;
|
||||
read_count = reader.read_count;
|
||||
close(fd);
|
||||
error = "not a supported wasm module";
|
||||
return(false);
|
||||
@@ -972,13 +1010,13 @@ static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadat
|
||||
while(pos < file_size)
|
||||
{
|
||||
u8 section_id = 0;
|
||||
if(!wasm_pread_all(fd, pos++, §ion_id, 1, bytes_read))
|
||||
if(!reader.read(pos++, §ion_id, 1))
|
||||
{
|
||||
error = "malformed wasm section header";
|
||||
break;
|
||||
}
|
||||
u64 section_size = 0;
|
||||
if(!wasm_read_uleb_fd(fd, pos, file_size, section_size, bytes_read) || section_size > file_size - pos)
|
||||
if(!reader.read_uleb(pos, file_size, section_size) || section_size > file_size - pos)
|
||||
{
|
||||
error = "malformed wasm section header";
|
||||
break;
|
||||
@@ -988,7 +1026,7 @@ static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadat
|
||||
{
|
||||
u64 cursor = pos;
|
||||
u64 name_len = 0;
|
||||
if(!wasm_read_uleb_fd(fd, cursor, section_end, name_len, bytes_read) || name_len > section_end - cursor)
|
||||
if(!reader.read_uleb(cursor, section_end, name_len) || name_len > section_end - cursor)
|
||||
{
|
||||
error = "malformed custom section name";
|
||||
break;
|
||||
@@ -997,7 +1035,7 @@ static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadat
|
||||
if(name_len <= 64)
|
||||
{
|
||||
name.resize((size_t)name_len);
|
||||
if(name_len && !wasm_pread_all(fd, cursor, (u8*)&name[0], (size_t)name_len, bytes_read))
|
||||
if(name_len && !reader.read(cursor, (u8*)&name[0], (size_t)name_len))
|
||||
{
|
||||
error = "malformed custom section name";
|
||||
break;
|
||||
@@ -1011,7 +1049,7 @@ static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadat
|
||||
break;
|
||||
}
|
||||
std::vector<u8> section((size_t)section_size);
|
||||
if(section_size && !wasm_pread_all(fd, pos, section.data(), section.size(), bytes_read))
|
||||
if(section_size && !reader.read(pos, section.data(), section.size()))
|
||||
{
|
||||
error = "cannot read wasm metadata section";
|
||||
break;
|
||||
@@ -1023,6 +1061,14 @@ static bool wasm_read_metadata_file(const String& path, std::vector<u8>& metadat
|
||||
}
|
||||
pos = section_end;
|
||||
}
|
||||
bytes_read = reader.bytes_read;
|
||||
read_count = reader.read_count;
|
||||
struct stat final_st;
|
||||
if(error == "" && (fstat(fd, &final_st) != 0 || final_st.st_dev != st.st_dev || final_st.st_ino != st.st_ino ||
|
||||
final_st.st_mtim.tv_sec != st.st_mtim.tv_sec || final_st.st_mtim.tv_nsec != st.st_mtim.tv_nsec ||
|
||||
final_st.st_ctim.tv_sec != st.st_ctim.tv_sec || final_st.st_ctim.tv_nsec != st.st_ctim.tv_nsec ||
|
||||
final_st.st_size != st.st_size))
|
||||
error = "wasm artifact changed while loading metadata";
|
||||
close(fd);
|
||||
if(error != "")
|
||||
return(false);
|
||||
@@ -1187,7 +1233,7 @@ public:
|
||||
std::vector<u8> bytes;
|
||||
auto read_start = std::chrono::steady_clock::now();
|
||||
bool read_ok = profile.serialized_cache_hit
|
||||
? wasm_read_metadata_file(wasm_path, bytes, error, profile.read_bytes, modified_ns, changed_ns, unit->size)
|
||||
? wasm_read_metadata_file(wasm_path, bytes, error, profile.read_bytes, profile.read_count, modified_ns, changed_ns, unit->size)
|
||||
: wasm_read_file(wasm_path, bytes);
|
||||
if(!profile.serialized_cache_hit)
|
||||
profile.read_bytes = bytes.size();
|
||||
@@ -2239,6 +2285,7 @@ private:
|
||||
unit_module_lookup_total_us += module_profile.lookup_us;
|
||||
unit_module_read_total_us += module_profile.read_us;
|
||||
unit_module_read_bytes += module_profile.read_bytes;
|
||||
unit_module_read_count += module_profile.read_count;
|
||||
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;
|
||||
@@ -2261,6 +2308,7 @@ private:
|
||||
operation.lookup_us = module_profile.lookup_us;
|
||||
operation.read_us = module_profile.read_us;
|
||||
operation.read_bytes = module_profile.read_bytes;
|
||||
operation.read_count = module_profile.read_count;
|
||||
operation.parse_us = module_profile.parse_us;
|
||||
operation.build_us = module_profile.compile_us;
|
||||
operation.classify_us = module_profile.classify_us;
|
||||
@@ -3176,6 +3224,7 @@ private:
|
||||
response["unit_module_lookup_us"] = (f64)self->unit_module_lookup_total_us;
|
||||
response["unit_module_read_us"] = (f64)self->unit_module_read_total_us;
|
||||
response["unit_module_read_bytes"] = (f64)self->unit_module_read_bytes;
|
||||
response["unit_module_read_count"] = (f64)self->unit_module_read_count;
|
||||
response["unit_module_parse_us"] = (f64)self->unit_module_parse_total_us;
|
||||
response["unit_module_compile_us"] = (f64)self->unit_module_compile_total_us;
|
||||
response["unit_module_classify_us"] = (f64)self->unit_module_classify_total_us;
|
||||
@@ -3192,6 +3241,7 @@ private:
|
||||
item["lookup_us"] = (f64)operation.lookup_us;
|
||||
item["read_us"] = (f64)operation.read_us;
|
||||
item["read_bytes"] = (f64)operation.read_bytes;
|
||||
item["read_count"] = (f64)operation.read_count;
|
||||
item["parse_us"] = (f64)operation.parse_us;
|
||||
item["build_us"] = (f64)operation.build_us;
|
||||
item["classify_us"] = (f64)operation.classify_us;
|
||||
|
||||
Reference in New Issue
Block a user