diff --git a/crates/benilla-app/src/addon_harness/tick_bench_tests.rs b/crates/benilla-app/src/addon_harness/tick_bench_tests.rs index ba9b4d67..648f4bee 100644 --- a/crates/benilla-app/src/addon_harness/tick_bench_tests.rs +++ b/crates/benilla-app/src/addon_harness/tick_bench_tests.rs @@ -1252,6 +1252,23 @@ fn hover_frame(s: &mut UiScript, company: Company, plates: &[PlateFeed], rebuild /// text (0.1 requests a frame, the same held or rebuilt): neither the patch chain nor the font /// engine is in this cost, so neither can explain the part of grom's 90-to-31 fps that the VM /// does not account for. Whatever the rest is, it is app-side, outside this harness. +/// +/// **What the derive tally and the frame count add** (both printed per window): a rebuild gives up +/// naming the layout graph exactly **once each**, always at `model.rs`'s `frame_id` — which is the +/// mint of a frame the model has not seen before, and the one write that genuinely cannot be named +/// precisely, since a new node has to join the cached graph. A held hover does not. +/// +/// The frame is not ours. `OctoPawn` hangs an `OnShow` on `GameTooltip` and, on every show, +/// creates an anonymous `CreateFrame("Frame")` purely to own a one-shot `OnUpdate` delay — twice, +/// from `Scoring/ScoringCore.lua:540` and `UI/Paperdoll/Pdmo.lua:101`, which is the ordinary 1.12 +/// way to write `C_Timer.After`. So **every** tooltip raise on his interface mints frames and +/// therefore re-derives, on the reference client too. The live frame count rises by far less than +/// the number created (137 against 480 here), so Lua reclaims most of them; it is a cost per +/// raise, not an unbounded leak. +/// +/// Kept as instrumentation rather than acted on: the lever would be letting a brand-new leaf node +/// join the graph without a full derive, which is a layout-engine change and wants its own +/// measurement. #[test] #[ignore = "bench — needs WOW_DATA and the player's AddOns; run explicitly with --release"] fn a_mouseover_plate_rebuilt_every_frame() { @@ -1273,6 +1290,7 @@ fn a_mouseover_plate_rebuilt_every_frame() { font_us: 0.0, }); install_live_asset_probes(&mut s, &data, &root, &PROBES); + let _ = s.take_layout_derive_sites(); // the first take is what arms the tally let plates = plate_feeds(); let per = f64::from(FRAMES); @@ -1327,6 +1345,17 @@ fn a_mouseover_plate_rebuilt_every_frame() { (after.2 - before.2) as f64 / per, (after.3 - before.3) / per / 1000.0, ); + for (site, n) in s.take_layout_derive_sites().iter().take(5) { + println!("[hover] {shape} {label} {n:5} derives from {site}"); + } + println!( + "[hover] {shape} {label} counts {:?}", + s.tick_profile_counts() + .iter() + .filter(|(l, _)| *l == "frames" || *l == "regions") + .map(|(l, n)| format!("{l} {n:.0}")) + .collect::>() + ); let errs = s.take_errors(); if !errs.is_empty() { println!(