feat(runtime): trace visual cache sizes

This commit is contained in:
2026-07-18 13:28:27 +04:00
parent 2474e48020
commit 564edf0bc1
4 changed files with 146 additions and 32 deletions
+4 -1
View File
@@ -1093,6 +1093,9 @@ mod tests {
request_count: 64,
graph_node_count: 128,
graph_edge_count: 192,
wear_cache_entries: 8,
material_cache_entries: 16,
texture_cache_entries: 32,
},
)?;
let progress = std::fs::read_to_string(&path).map_err(|err| err.to_string())?;
@@ -1100,7 +1103,7 @@ mod tests {
assert_eq!(
progress,
"Starting\telapsed_ms=0\nGraphVisualMaterials\telapsed_ms=12\nGraphVisualMaterialRequests { request_count: 64, graph_node_count: 128, graph_edge_count: 192 }\telapsed_ms=34\n"
"Starting\telapsed_ms=0\nGraphVisualMaterials\telapsed_ms=12\nGraphVisualMaterialRequests { request_count: 64, graph_node_count: 128, graph_edge_count: 192, wear_cache_entries: 8, material_cache_entries: 16, texture_cache_entries: 32 }\telapsed_ms=34\n"
);
Ok(())
}
+115 -30
View File
@@ -52,6 +52,7 @@ const VISUAL_DEPENDENCY_PROGRESS_INTERVAL: usize = 64;
type WearValidationCache =
HashMap<(NormalizedPath, Vec<u8>), Result<fparkan_material::WearTable, String>>;
type TextureValidationCache = HashMap<Vec<u8>, Result<(), String>>;
/// Canonical terrain archive paths derived from a mission land reference.
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -483,6 +484,17 @@ pub enum VisualDependencyPhase {
Texture,
}
/// Validation-cache entries retained while expanding visual dependencies.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct VisualDependencyCacheCounts {
/// Distinct WEAR archive/name keys resolved so far.
pub wear_entries: usize,
/// Distinct MAT0 raw names resolved so far.
pub material_entries: usize,
/// Distinct TEXM archive/name keys resolved so far.
pub texture_entries: usize,
}
/// Throttled visual-dependency expansion progress.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct VisualDependencyProgress {
@@ -494,6 +506,8 @@ pub struct VisualDependencyProgress {
pub graph_node_count: usize,
/// Resource graph edges materialized before this request is resolved.
pub graph_edge_count: usize,
/// Validation-cache entries retained before this request is resolved.
pub cache_entries: VisualDependencyCacheCounts,
}
/// Errors raised while preparing CPU-side assets.
@@ -1241,10 +1255,18 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress<R: ResourceRep
wear_requests = wear_requests.saturating_add(1);
report_visual_dependency_progress(
&mut on_progress,
VisualDependencyPhase::Wear,
wear_requests,
graph.nodes.len(),
graph.edges.len(),
VisualDependencyProgress {
phase: VisualDependencyPhase::Wear,
request_count: wear_requests,
graph_node_count: graph.nodes.len(),
graph_edge_count: graph.edges.len(),
cache_entries: visual_dependency_cache_counts(
&wear_validation,
&material_validation,
&diffuse_texture_validation,
&lightmap_texture_validation,
),
},
);
match resolve_wear_table_cached(repository, mesh, &mut wear_validation) {
Ok(table) => {
@@ -1289,15 +1311,29 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress<R: ResourceRep
request_count: material_requests,
graph_node_count: graph.nodes.len(),
graph_edge_count: graph.edges.len(),
cache_entries: visual_dependency_cache_counts(
&wear_validation,
&material_validation,
&diffuse_texture_validation,
&lightmap_texture_validation,
),
});
for (material_index, _entry) in table.entries.iter().enumerate() {
material_requests = material_requests.saturating_add(1);
report_visual_dependency_progress(
&mut on_progress,
VisualDependencyPhase::Material,
material_requests,
graph.nodes.len(),
graph.edges.len(),
VisualDependencyProgress {
phase: VisualDependencyPhase::Material,
request_count: material_requests,
graph_node_count: graph.nodes.len(),
graph_edge_count: graph.edges.len(),
cache_entries: visual_dependency_cache_counts(
&wear_validation,
&material_validation,
&diffuse_texture_validation,
&lightmap_texture_validation,
),
},
);
let Ok(material_index) = u16::try_from(material_index) else {
push_visual_failure(
@@ -1347,10 +1383,18 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress<R: ResourceRep
texture_requests = texture_requests.saturating_add(1);
report_visual_dependency_progress(
&mut on_progress,
VisualDependencyPhase::Texture,
texture_requests,
graph.nodes.len(),
graph.edges.len(),
VisualDependencyProgress {
phase: VisualDependencyPhase::Texture,
request_count: texture_requests,
graph_node_count: graph.nodes.len(),
graph_edge_count: graph.edges.len(),
cache_entries: visual_dependency_cache_counts(
&wear_validation,
&material_validation,
&diffuse_texture_validation,
&lightmap_texture_validation,
),
},
);
report.texture_request_count += 1;
match resolve_texm_validation_cached(
@@ -1415,10 +1459,18 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress<R: ResourceRep
texture_requests = texture_requests.saturating_add(1);
report_visual_dependency_progress(
&mut on_progress,
VisualDependencyPhase::Texture,
texture_requests,
graph.nodes.len(),
graph.edges.len(),
VisualDependencyProgress {
phase: VisualDependencyPhase::Texture,
request_count: texture_requests,
graph_node_count: graph.nodes.len(),
graph_edge_count: graph.edges.len(),
cache_entries: visual_dependency_cache_counts(
&wear_validation,
&material_validation,
&diffuse_texture_validation,
&lightmap_texture_validation,
),
},
);
report.lightmap_request_count += 1;
match resolve_texm_validation_cached(
@@ -1484,18 +1536,29 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress<R: ResourceRep
fn report_visual_dependency_progress(
on_progress: &mut impl FnMut(VisualDependencyProgress),
phase: VisualDependencyPhase,
request_count: usize,
graph_node_count: usize,
graph_edge_count: usize,
progress: VisualDependencyProgress,
) {
if request_count == 1 || request_count.is_multiple_of(VISUAL_DEPENDENCY_PROGRESS_INTERVAL) {
on_progress(VisualDependencyProgress {
phase,
request_count,
graph_node_count,
graph_edge_count,
});
if progress.request_count == 1
|| progress
.request_count
.is_multiple_of(VISUAL_DEPENDENCY_PROGRESS_INTERVAL)
{
on_progress(progress);
}
}
fn visual_dependency_cache_counts(
wear_validation: &WearValidationCache,
material_validation: &HashMap<Vec<u8>, Result<ResolvedMaterial, String>>,
diffuse_texture_validation: &TextureValidationCache,
lightmap_texture_validation: &TextureValidationCache,
) -> VisualDependencyCacheCounts {
VisualDependencyCacheCounts {
wear_entries: wear_validation.len(),
material_entries: material_validation.len(),
texture_entries: diffuse_texture_validation
.len()
.saturating_add(lightmap_texture_validation.len()),
}
}
@@ -2336,10 +2399,17 @@ mod tests {
for request_count in 1..=129 {
report_visual_dependency_progress(
&mut |event| progress.push(event),
VisualDependencyPhase::Texture,
VisualDependencyProgress {
phase: VisualDependencyPhase::Texture,
request_count,
37,
41,
graph_node_count: 37,
graph_edge_count: 41,
cache_entries: VisualDependencyCacheCounts {
wear_entries: 3,
material_entries: 5,
texture_entries: 7,
},
},
);
}
@@ -2351,18 +2421,33 @@ mod tests {
request_count: 1,
graph_node_count: 37,
graph_edge_count: 41,
cache_entries: VisualDependencyCacheCounts {
wear_entries: 3,
material_entries: 5,
texture_entries: 7,
},
},
VisualDependencyProgress {
phase: VisualDependencyPhase::Texture,
request_count: 64,
graph_node_count: 37,
graph_edge_count: 41,
cache_entries: VisualDependencyCacheCounts {
wear_entries: 3,
material_entries: 5,
texture_entries: 7,
},
},
VisualDependencyProgress {
phase: VisualDependencyPhase::Texture,
request_count: 128,
graph_node_count: 37,
graph_edge_count: 41,
cache_entries: VisualDependencyCacheCounts {
wear_entries: 3,
material_entries: 5,
texture_entries: 7,
},
},
]
);
+18
View File
@@ -133,6 +133,12 @@ pub enum MissionLoadPhase {
graph_node_count: usize,
/// Graph edges materialized before the request.
graph_edge_count: usize,
/// Distinct WEAR validation keys retained before the request.
wear_cache_entries: usize,
/// Distinct MAT0 validation keys retained before the request.
material_cache_entries: usize,
/// Distinct TEXM validation keys retained before the request.
texture_cache_entries: usize,
},
/// Validate TEXM documents while expanding visual dependencies.
GraphVisualTextures,
@@ -144,6 +150,12 @@ pub enum MissionLoadPhase {
graph_node_count: usize,
/// Graph edges materialized before the request.
graph_edge_count: usize,
/// Distinct WEAR validation keys retained before the request.
wear_cache_entries: usize,
/// Distinct MAT0 validation keys retained before the request.
material_cache_entries: usize,
/// Distinct TEXM validation keys retained before the request.
texture_cache_entries: usize,
},
/// Prepare all reachable visual/resource dependencies.
Assets,
@@ -747,6 +759,9 @@ fn load_mission_with_options_and_progress(
request_count: progress.request_count,
graph_node_count: progress.graph_node_count,
graph_edge_count: progress.graph_edge_count,
wear_cache_entries: progress.cache_entries.wear_entries,
material_cache_entries: progress.cache_entries.material_entries,
texture_cache_entries: progress.cache_entries.texture_entries,
})
}
VisualDependencyPhase::Texture => {
@@ -754,6 +769,9 @@ fn load_mission_with_options_and_progress(
request_count: progress.request_count,
graph_node_count: progress.graph_node_count,
graph_edge_count: progress.graph_edge_count,
wear_cache_entries: progress.cache_entries.wear_entries,
material_cache_entries: progress.cache_entries.material_entries,
texture_cache_entries: progress.cache_entries.texture_entries,
})
}
};
+8
View File
@@ -1133,6 +1133,14 @@ probe recorded MAT0 request 3 at 52 nodes / 51 edges and request 4 at 55 nodes
they do not change traversal order, node or edge identities, provenance,
validation, cache semantics, or rendering.
The same throttled snapshots now retain the number of distinct validation-cache
keys for WEAR, MAT0, and TEXM before the request. In a fresh 50-second Part 2
probe, MAT0 request 3 recorded cache counts 2 / 3 / 3 and request 4 recorded
3 / 4 / 4, while the graph moved from 52 / 51 to 55 / 54 nodes / edges. The
counts distinguish cache growth from graph growth without adding per-request
file writes or asserting which parser, archive I/O operation, or allocation
caused the elapsed interval.
`fparkan-game --load-progress` now initializes its file with `Starting` and
appends each later mission-load event instead of replacing the prior line. A
bounded probe can therefore retain both MAT0 and TEXM request milestones even