Correlate infrastructure prelude candidate classes
This commit is contained in:
parent
1a0653cff1
commit
5219d5a9ce
3 changed files with 187 additions and 0 deletions
|
|
@ -2154,6 +2154,9 @@ pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSummary {
|
||||||
pub dominant_candidate_pattern:
|
pub dominant_candidate_pattern:
|
||||||
Option<SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePattern>,
|
Option<SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePattern>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub candidate_pattern_correlations:
|
||||||
|
Vec<SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePatternCorrelation>,
|
||||||
|
#[serde(default)]
|
||||||
pub profile_span_correlations:
|
pub profile_span_correlations:
|
||||||
Vec<SmpSavePlacedStructureDynamicSideBufferNamePreludeProfileSpanCorrelation>,
|
Vec<SmpSavePlacedStructureDynamicSideBufferNamePreludeProfileSpanCorrelation>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -2185,6 +2188,27 @@ pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSample {
|
||||||
pub previous_profile_chunk_len_to_next_name_or_end: Option<usize>,
|
pub previous_profile_chunk_len_to_next_name_or_end: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePatternCorrelation {
|
||||||
|
pub child_count_candidate: u16,
|
||||||
|
pub child_count_candidate_hex: String,
|
||||||
|
pub saved_primary_child_byte_candidate: u8,
|
||||||
|
pub saved_primary_child_byte_candidate_hex: String,
|
||||||
|
pub row_count: usize,
|
||||||
|
pub unique_name_pair_count: usize,
|
||||||
|
pub unique_profile_span_count: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub dominant_primary_name: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub dominant_secondary_name: Option<String>,
|
||||||
|
pub dominant_name_pair_count: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub dominant_profile_span: Option<usize>,
|
||||||
|
pub dominant_profile_span_count: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub sample_rows: Vec<SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSample>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeProfileSpanCorrelation {
|
pub struct SmpSavePlacedStructureDynamicSideBufferNamePreludeProfileSpanCorrelation {
|
||||||
pub previous_profile_chunk_len_to_next_name_or_end: usize,
|
pub previous_profile_chunk_len_to_next_name_or_end: usize,
|
||||||
|
|
@ -4484,6 +4508,32 @@ fn build_infrastructure_asset_trace_report(
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
"no dominant post-profile outlier breakdown was available".to_string()
|
"no dominant post-profile outlier breakdown was available".to_string()
|
||||||
}),
|
}),
|
||||||
|
side_buffer
|
||||||
|
.and_then(|probe| probe.payload_envelope_summary.as_ref())
|
||||||
|
.and_then(|summary| summary.name_prelude_candidate_summary.as_ref())
|
||||||
|
.map(|summary| {
|
||||||
|
format!(
|
||||||
|
"candidate-pattern correlations now split the remaining prelude classes cleanly too: {:?}",
|
||||||
|
summary
|
||||||
|
.candidate_pattern_correlations
|
||||||
|
.iter()
|
||||||
|
.map(|entry| format!(
|
||||||
|
"{}/{} rows={} dominant-name={:?}/{:?} x{} dominant-prev-span={:?} x{}",
|
||||||
|
entry.child_count_candidate_hex,
|
||||||
|
entry.saved_primary_child_byte_candidate_hex,
|
||||||
|
entry.row_count,
|
||||||
|
entry.dominant_primary_name,
|
||||||
|
entry.dominant_secondary_name,
|
||||||
|
entry.dominant_name_pair_count,
|
||||||
|
entry.dominant_profile_span,
|
||||||
|
entry.dominant_profile_span_count
|
||||||
|
))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
"no candidate-pattern correlation summary was available".to_string()
|
||||||
|
}),
|
||||||
side_buffer
|
side_buffer
|
||||||
.and_then(|probe| probe.payload_envelope_summary.as_ref())
|
.and_then(|probe| probe.payload_envelope_summary.as_ref())
|
||||||
.and_then(|summary| summary.name_prelude_candidate_summary.as_ref())
|
.and_then(|summary| summary.name_prelude_candidate_summary.as_ref())
|
||||||
|
|
@ -13168,6 +13218,125 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
.then_with(|| right_key.cmp(left_key))
|
.then_with(|| right_key.cmp(left_key))
|
||||||
})
|
})
|
||||||
.map(|(value, count)| (*value, *count));
|
.map(|(value, count)| (*value, *count));
|
||||||
|
let mut name_prelude_pattern_groups =
|
||||||
|
BTreeMap::<(u16, u8), Vec<(usize, Option<String>, Option<String>, Option<usize>)>>::new();
|
||||||
|
for (
|
||||||
|
name_tag_relative_offset,
|
||||||
|
primary_name,
|
||||||
|
secondary_name,
|
||||||
|
child_count_candidate,
|
||||||
|
saved_primary_child_byte_candidate,
|
||||||
|
previous_span,
|
||||||
|
) in &name_prelude_candidate_rows
|
||||||
|
{
|
||||||
|
name_prelude_pattern_groups
|
||||||
|
.entry((*child_count_candidate, *saved_primary_child_byte_candidate))
|
||||||
|
.or_default()
|
||||||
|
.push((
|
||||||
|
*name_tag_relative_offset,
|
||||||
|
primary_name.clone(),
|
||||||
|
secondary_name.clone(),
|
||||||
|
*previous_span,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let candidate_pattern_correlations = name_prelude_pattern_groups
|
||||||
|
.into_iter()
|
||||||
|
.map(
|
||||||
|
|(
|
||||||
|
(child_count_candidate, saved_primary_child_byte_candidate),
|
||||||
|
rows,
|
||||||
|
)| {
|
||||||
|
let mut name_pair_counts =
|
||||||
|
BTreeMap::<(Option<String>, Option<String>), usize>::new();
|
||||||
|
let mut profile_span_counts = BTreeMap::<usize, usize>::new();
|
||||||
|
for (_, primary_name, secondary_name, previous_span) in &rows {
|
||||||
|
*name_pair_counts
|
||||||
|
.entry((primary_name.clone(), secondary_name.clone()))
|
||||||
|
.or_default() += 1;
|
||||||
|
if let Some(previous_span) = previous_span {
|
||||||
|
*profile_span_counts.entry(*previous_span).or_default() += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let dominant_name_pair = name_pair_counts
|
||||||
|
.iter()
|
||||||
|
.max_by(|(left_key, left_count), (right_key, right_count)| {
|
||||||
|
left_count
|
||||||
|
.cmp(right_count)
|
||||||
|
.then_with(|| right_key.cmp(left_key))
|
||||||
|
})
|
||||||
|
.map(|((primary_name, secondary_name), count)| {
|
||||||
|
(primary_name.clone(), secondary_name.clone(), *count)
|
||||||
|
});
|
||||||
|
let dominant_profile_span = profile_span_counts
|
||||||
|
.iter()
|
||||||
|
.max_by(|(left_key, left_count), (right_key, right_count)| {
|
||||||
|
left_count
|
||||||
|
.cmp(right_count)
|
||||||
|
.then_with(|| right_key.cmp(left_key))
|
||||||
|
})
|
||||||
|
.map(|(span, count)| (*span, *count));
|
||||||
|
SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidatePatternCorrelation {
|
||||||
|
child_count_candidate,
|
||||||
|
child_count_candidate_hex: format!("0x{child_count_candidate:04x}"),
|
||||||
|
saved_primary_child_byte_candidate,
|
||||||
|
saved_primary_child_byte_candidate_hex: format!(
|
||||||
|
"0x{saved_primary_child_byte_candidate:02x}"
|
||||||
|
),
|
||||||
|
row_count: rows.len(),
|
||||||
|
unique_name_pair_count: name_pair_counts.len(),
|
||||||
|
unique_profile_span_count: profile_span_counts.len(),
|
||||||
|
dominant_primary_name: dominant_name_pair
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|(primary_name, _, _)| primary_name.clone()),
|
||||||
|
dominant_secondary_name: dominant_name_pair
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|(_, secondary_name, _)| secondary_name.clone()),
|
||||||
|
dominant_name_pair_count: dominant_name_pair
|
||||||
|
.map(|(_, _, count)| count)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
dominant_profile_span: dominant_profile_span
|
||||||
|
.map(|(profile_span, _)| profile_span),
|
||||||
|
dominant_profile_span_count: dominant_profile_span
|
||||||
|
.map(|(_, count)| count)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
sample_rows: rows
|
||||||
|
.iter()
|
||||||
|
.take(8)
|
||||||
|
.enumerate()
|
||||||
|
.map(
|
||||||
|
|(
|
||||||
|
sample_index,
|
||||||
|
(
|
||||||
|
name_tag_relative_offset,
|
||||||
|
primary_name,
|
||||||
|
secondary_name,
|
||||||
|
previous_profile_chunk_len_to_next_name_or_end,
|
||||||
|
),
|
||||||
|
)| {
|
||||||
|
SmpSavePlacedStructureDynamicSideBufferNamePreludeCandidateSample {
|
||||||
|
sample_index,
|
||||||
|
name_tag_relative_offset: *name_tag_relative_offset,
|
||||||
|
primary_name: primary_name.clone(),
|
||||||
|
secondary_name: secondary_name.clone(),
|
||||||
|
child_count_candidate,
|
||||||
|
child_count_candidate_hex: format!(
|
||||||
|
"0x{child_count_candidate:04x}"
|
||||||
|
),
|
||||||
|
saved_primary_child_byte_candidate,
|
||||||
|
saved_primary_child_byte_candidate_hex: format!(
|
||||||
|
"0x{saved_primary_child_byte_candidate:02x}"
|
||||||
|
),
|
||||||
|
previous_profile_chunk_len_to_next_name_or_end:
|
||||||
|
*previous_profile_chunk_len_to_next_name_or_end,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.take(8)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let mut name_prelude_profile_span_groups =
|
let mut name_prelude_profile_span_groups =
|
||||||
BTreeMap::<usize, Vec<(u16, u8)>>::new();
|
BTreeMap::<usize, Vec<(u16, u8)>>::new();
|
||||||
for (_, _, _, child_count_candidate, saved_primary_child_byte_candidate, previous_span) in
|
for (_, _, _, child_count_candidate, saved_primary_child_byte_candidate, previous_span) in
|
||||||
|
|
@ -13272,6 +13441,7 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
.map(|(_, count)| count)
|
.map(|(_, count)| count)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
dominant_candidate_pattern: dominant_name_prelude_candidate_pattern.clone(),
|
dominant_candidate_pattern: dominant_name_prelude_candidate_pattern.clone(),
|
||||||
|
candidate_pattern_correlations,
|
||||||
profile_span_correlations,
|
profile_span_correlations,
|
||||||
sample_rows: name_prelude_candidate_rows
|
sample_rows: name_prelude_candidate_rows
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -24083,6 +24253,7 @@ mod tests {
|
||||||
count: 110,
|
count: 110,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
candidate_pattern_correlations: Vec::new(),
|
||||||
profile_span_correlations: Vec::new(),
|
profile_span_correlations: Vec::new(),
|
||||||
sample_rows: Vec::new(),
|
sample_rows: Vec::new(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2992,6 +2992,14 @@ The low helper strip beneath that shared family is tighter now too: `0x0052ecd0`
|
||||||
`TrackCapST_Cap.3dp / Infrastructure` row with compact prefix `0xff0000ff / 0x0001 / 0xff`.
|
`TrackCapST_Cap.3dp / Infrastructure` row with compact prefix `0xff0000ff / 0x0001 / 0xff`.
|
||||||
So the next infrastructure pass should target the `BallastCap` outlier family first instead of
|
So the next infrastructure pass should target the `BallastCap` outlier family first instead of
|
||||||
spending time on the already-dominant bridge-section class.
|
spending time on the already-dominant bridge-section class.
|
||||||
|
The candidate-pattern classes are explicit now too: `0x0055 / 0x00` is a pure
|
||||||
|
`BallastCapST_Cap.3dp / Infrastructure` class across `18` rows, always preceded by a zero-length
|
||||||
|
prior profile span, while `0x0002 / 0xff` is a pure
|
||||||
|
`BridgeSTWood_Section.3dp / Infrastructure` class across `18` rows with dominant prior profile
|
||||||
|
span `0x06` (`10` rows). So the next infrastructure pass should split its owner questions the
|
||||||
|
same way: treat `0x0055 / 0x00` as a `BallastCap`-specific boundary artifact class, and treat
|
||||||
|
`0x0002 / 0xff` as the likely bridge-specific two-child / clone-path class above
|
||||||
|
`0x0048a1e0/0x0048dcf0`.
|
||||||
The child loader family is explicit now too: local `.rdata` at `0x005cfd00` proves the
|
The child loader family is explicit now too: local `.rdata` at `0x005cfd00` proves the
|
||||||
`Infrastructure` child vtable uses the shared tagged callback strip directly, with
|
`Infrastructure` child vtable uses the shared tagged callback strip directly, with
|
||||||
`+0x40 = 0x00455fc0`, `+0x48 = 0x00455870`, and `+0x4c = 0x00455930`. So the remaining
|
`+0x40 = 0x00455fc0`, `+0x48 = 0x00455870`, and `+0x4c = 0x00455930`. So the remaining
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,14 @@ Working rule:
|
||||||
`TrackCapST_Cap.3dp / Infrastructure` row with compact prefix `0xff0000ff / 0x0001 / 0xff`.
|
`TrackCapST_Cap.3dp / Infrastructure` row with compact prefix `0xff0000ff / 0x0001 / 0xff`.
|
||||||
So the next infrastructure slice should target the `BallastCap` outlier family first, not the
|
So the next infrastructure slice should target the `BallastCap` outlier family first, not the
|
||||||
already-dominant bridge-section class.
|
already-dominant bridge-section class.
|
||||||
|
- The candidate-pattern classes are now explicit across the whole stream too: `0x0055 / 0x00`
|
||||||
|
is a pure `BallastCapST_Cap.3dp / Infrastructure` class across `18` rows, always preceded by a
|
||||||
|
zero-length prior profile span, while `0x0002 / 0xff` is a pure
|
||||||
|
`BridgeSTWood_Section.3dp / Infrastructure` class across `18` rows with dominant prior profile
|
||||||
|
span `0x06` (`10` rows). So the next infrastructure pass should split its owner questions:
|
||||||
|
treat `0x0055 / 0x00` as a `BallastCap`-specific boundary artifact class, and treat
|
||||||
|
`0x0002 / 0xff` as the likely bridge-specific two-child / clone-path class above
|
||||||
|
`0x0048a1e0/0x0048dcf0`.
|
||||||
- Reconstruct the save-side region record body on top of the newly corrected non-direct tagged
|
- Reconstruct the save-side region record body on top of the newly corrected non-direct tagged
|
||||||
region seam (`0x5209/0x520a/0x520b`, stride hint `0x06`, `Marker09` record stems) now that the
|
region seam (`0x5209/0x520a/0x520b`, stride hint `0x06`, `Marker09` record stems) now that the
|
||||||
`0x55f3` payload is known to be fully consumed by the embedded profile collection on grounded
|
`0x55f3` payload is known to be fully consumed by the embedded profile collection on grounded
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue