Explicit carve reach R (diagnostic, default unbounded): R=2.5 m -> 1.56 cm max displacement, 106 deg max normal change; R=4 m -> 0.63 cm but 53 deg normals. Fails the bar; readiness gain small and inconsistent (TN -5%, VS +6-7%). No world change (v214). Fast tier PASS. R43: Unreal SW bReady 2.16 s = serial sign-edge repair (1.94 s, 10.9M corrections; parallelSignEdgeRepair exists but off); ~0.45 s of SerializeResolvedWorld = adapter SW route search. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
68 lines
16 KiB
Markdown
68 lines
16 KiB
Markdown
## Ranked findings
|
||
|
||
1. **[TRACE] The extra ~2 seconds are inside Core’s shape build.** Across the three final runs, SW’s `core_compile_start → core_bready` interval is **2.171, 2.157, and 2.038 s**; FI’s is **0.173, 0.184, and 0.187 s**. The median gap is **1.973 s**. [SW traces](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.trace.jsonl:24>), [FI traces](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-1.trace.jsonl:24>)
|
||
|
||
**[TRACE]** The SW `ShapeStage`’s median `sign_edge_distances` time is **1.942 s**, versus **8.8 ms** for FI. SW repairs **10,864,702** endpoint proxies, with **10,864,427** occupancy corrections; FI records zero endpoint proxies. Both compile **138,188,413 nodes** and use the same assembly, recipe, and plan hashes. [SW shape log](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.stdout.log:1376>), [FI shape log](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-1.stdout.log:1132>), [L92 hashes](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux92/REPORT.md:26>)
|
||
|
||
**[CODE]** `FStandaloneShapeWorld::Build` runs `ApplyDetailBand`, then `CompleteSignEdgeDistances`; the latter calls `AnalyticDensityAt` for missing edge samples. The parallel repair branch exists, but `parallelSignEdgeRepair` defaults to `false` and Unreal does not set it on this request. [Shape build](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3331>), [serial repair](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:12000>), [request default](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h:1592>), [Unreal request](</home/jahni/VoxelM/Plugins/VoxelForge/Private/VoxelWorld.cpp:7807>)
|
||
|
||
**[INFERENCE]** The dominant delay is serial sign-edge repair over the SW-start shape region. The different spawn heights support that explanation: SW starts at −200 m, within the SurfaceWorld stratum; FI starts at −737 m. **Falsifier:** an identical SW run showing sign-edge repair below roughly 100 ms, or showing that the repair is not part of `World::compile`, would overturn this attribution. [SW spawn](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.trace.jsonl:27>), [FI spawn](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-1.trace.jsonl:27>)
|
||
|
||
2. **[TRACE] The adapter’s route search is a separate ~0.45 s cost before compile launch.** In the measured SW run, serialization takes **466.957 ms**. The corresponding route logs span about **452 ms** from the failed legacy candidate set to the bounded-mouth candidate result; that fallback visits 78,408 candidates and ends with only three sweep attempts. [SW trace](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.trace.jsonl:17>), [SW route logs](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.log:928>)
|
||
|
||
**[CODE]** This runs in `BuildFiniteSurfaceRoute`, called while `BuildSurfaceStratumPlan` assembles the manifest inside `SerializeResolvedWorld`. It finishes before `core_compile_launch`; it cannot explain the launch-to-`bReady` interval. [Route search](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:445>), [plan call](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:839>), [manifest build](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:1635>), [compile launch](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.trace.jsonl:23>)
|
||
|
||
**[INFERENCE]** The route search explains much of the **shared** ~466–468 ms serialization cost in both FI and SW, but not why SW takes longer than FI after compile starts. The log span is strong attribution, though it is not a per-function timer. **Falsifier:** a direct timer showing the candidate loops take far less than 400 ms, or showing they fall outside the measured exporter interval.
|
||
|
||
3. **[CODE][TRACE] The “radius 6 / max clip 6” values are the Settings asset values, not the Core compile settings in these traces.** Core uses `CoreClipRadius=3` and `CoreMaxClipLevel=8`; the adapter writes those values into the snapshot, and the runtime log says `clip_radius=3 max_level=8`. The trace’s `settings_resolved` event reports the separate Settings values 6/6. [Core defaults](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelWorld.h:310>), [snapshot override](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:2104>), [trace Settings values](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.trace.jsonl:3>), [runtime Core values](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.log:932>)
|
||
|
||
**[INFERENCE]** Changing the legacy Settings radius to 3 would not fix this Core compile; it already uses 3. **Falsifier:** inspecting the Core snapshot actually consumed by `World` and finding radius 6 / max level 6.
|
||
|
||
4. **[CODE][TRACE] Far parents, recipe differences, and long validation do not explain this gap.** Unreal sets `Request.includeFarWorld=false`, and the SW logs report `far_parents=0.000 ms`; FI and SW also log the same assembly/recipe/plan hashes. Passage validation is about 1.2–1.7 ms. [Request](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:7807>), [far build condition](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3339>), [SW shape stages](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.stdout.log:1379>)
|
||
|
||
**[INFERENCE]** Neither another plan path nor a debug/validation pass accounts for the 1.97 s FI/SW gap. **Falsifier:** a run with different plan hashes, nonzero far-parent time, or an unmeasured validation stage above hundreds of milliseconds.
|
||
|
||
## Trace arithmetic
|
||
|
||
**[TRACE]** These are direct subtractions of `core_compile_start.t_s` from `core_bready.t_s`:
|
||
|
||
| Arrival | Repeat 1 | Repeat 2 | Repeat 3 | Median |
|
||
|---|---:|---:|---:|---:|
|
||
| FI | `.742608 − .569354 = .173254 s` | `.749704 − .565919 = .183785 s` | `.796746 − .609896 = .186850 s` | `.183785 s` |
|
||
| SW | `2.780194 − .608768 = 2.171426 s` | `2.737530 − .580978 = 2.156552 s` | `2.616805 − .578886 = 2.037919 s` | `2.156552 s` |
|
||
|
||
[FI trace 1](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-1.trace.jsonl:24>), [FI trace 2](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-2.trace.jsonl:24>), [FI trace 3](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-3.trace.jsonl:24>), [SW trace 1](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.trace.jsonl:24>), [SW trace 2](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-2.trace.jsonl:24>), [SW trace 3](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.trace.jsonl:24>)
|
||
|
||
**[TRACE]** The reported `compile_s` values differ by at most about 26 μs because the code samples the duration just before recording the event timestamp. The SW run 1 trace then shows `bReady` at **2.780194 s**, first tile `request` at **2.794163 s**, and scheduler admission at **2.794603 s**. So the ~2.75 s table value is almost entirely the wait for `bReady`; the first per-tile request is about **14 ms** after readiness. [Ready sample](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:7886>), [SW events](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.trace.jsonl:422>)
|
||
|
||
**[TRACE]** The detailed logs match the Core trace: median FI `ShapeStage` is **183.527 ms**, median SW is **2,156.283 ms**; SW’s median sign-edge substage alone is **1,942.160 ms**. **Falsifier:** a trace/log pair with the same run identifiers but materially different `ShapeStage` and `core_bready` durations would break this mapping. [FI stage](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-2.stdout.log:1137>), [SW stage](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-2.stdout.log:1377>)
|
||
|
||
## What `SerializeResolvedWorld` does
|
||
|
||
**[CODE]** `BeginPlay` calls `InitializeVoxelForgeCoreWorld` synchronously; that function calls `SerializeResolvedWorld` before converting the result to UTF-8 and calling Core’s `ResolvedWorldSnapshot::FromJson`. [BeginPlay](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:2720>), [export and parse](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:7658>)
|
||
|
||
**[CODE]** The exporter reflects over Settings and nested Voxel objects with `TFieldIterator<FProperty>`, handles arrays/maps/sets/structs, serializes resolved strata and passages, and synchronously loads terrain-operation assets. It then builds or imports a world assembly, rebuilds the resolved layout, writes canonical manifest JSON, parses that manifest back into an Unreal JSON object, and writes the full snapshot JSON. [Reflection](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:966>), [asset load](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:2172>), [manifest build](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:1565>), [JSON embed/write](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:2036>)
|
||
|
||
**[TRACE]** L92 measures the whole exporter at **465.6 ms FI / 468.0 ms SW** and `FromJson` at **18.9 / 19.3 ms**. The route-search logs align with about **452 ms** inside the SW exporter window, so generic asset reflection and JSON handling are not supported as the main cause of the 466 ms. Their individual shares were not timed. [L92 timing and attribution note](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux92/REPORT.md:9>), [SW route logs](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.log:928>)
|
||
|
||
**[CODE]** Core’s public snapshot API currently exposes `FromJson`, getters, and layout helpers; the snapshot’s data constructor is private. A direct handoff is possible with a new typed Core builder, but the adapter would still need to map the resolved Unreal assets into Core-owned data. [Snapshot API](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h:1546>)
|
||
|
||
**[INFERENCE]** Direct typed construction could remove JSON encode/decode work, but it would not remove the route search. The measured ceiling for the parser plus the exporter’s non-route remainder is roughly **35 ms gross**; actual net savings may be smaller because a typed builder must still resolve and validate the owner data. **Falsifier:** a typed A/B that saves substantially more than that while generating the same plan would show unmeasured JSON work is larger than the current timing decomposition suggests.
|
||
|
||
**[CODE]** Running the existing exporter unchanged off-thread is unsafe: it reads Unreal `UObject` properties and calls `LoadSynchronous`. A split is possible: snapshot UObject-backed values on the game thread, then build the route/manifest from immutable Core inputs on a worker. **[INFERENCE]** That would reduce the game-thread hitch, but it will not reduce first-request wall time unless the work can overlap independent startup or use a precomputed manifest. **Falsifier:** a worker-thread run of the unchanged exporter that is shown safe for all UObject access and measurably reduces first admission without overlap.
|
||
|
||
## Smallest changes and measurements
|
||
|
||
1. **[INFERENCE] First SW experiment: enable the existing deterministic parallel sign-edge repair.** Set `Request.parallelSignEdgeRepair=true`; Core already has a parallel density evaluation path with sorted, deterministic publication. The current sign-edge stage is **1.94 s**, so that is the hard upper bound. L55 measured a different headless FI workload falling from **535 ms to 47 ms** with the same approach; using that ratio gives a rough SW estimate of **about 1.77 s saved**, not a result for this Unreal case. [Parallel implementation](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:12103>), [prior L55 result](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux55/REPORT.md:56>)
|
||
|
||
**[INFERENCE]** Cheapest confirmation: A/B that one request flag at the same SW spawn and worker count; compare existing `sign_edge_distances`, `ShapeStage`, `core_bready`, and output hashes. Keep the serial path if the SW hashes differ or the stage barely moves. **Falsifier:** the paired run saves under roughly 100 ms, or changes the exact SW outputs.
|
||
|
||
2. **[INFERENCE] For the separate ~0.45 s exporter cost, use an already generated manifest through the existing override path when a seed/layout-matched artifact is available.** `AttachValidatedWorldAssembly` parses and validates an imported manifest instead of building `BuildSurfaceStratumPlan` and searching candidates; preserving the existing manifest hash preserves the route plan and does not change the passage composer. Expected saving is **about 0.4–0.45 s**, subject to the artifact matching the resolved seed and strata. [Override branch](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:1577>)
|
||
|
||
**[INFERENCE]** Cheapest confirmation: one fixed-seed trace using the identical manifest; check that route-candidate logs disappear, hashes remain identical, and `SerializeResolvedWorld` falls by roughly the route-search span. **Falsifier:** the route search still runs, hashes change, or the exporter falls by much less than 0.4 s.
|
||
|
||
3. **[INFERENCE] Treat direct typed handoff as a small cleanup, not the startup fix.** It can target the roughly **19 ms** parse and some residual JSON work, but not the sign-edge repair or route search. **Falsifier:** a direct-builder A/B removes hundreds of milliseconds without changing route planning; that would show the current residual estimate is wrong.
|
||
|
||
4. **[TRACE][INFERENCE] Do not tune the legacy 6/6 clip values or raise the compile task priority as the first fix.** Core already runs 3/8, and launch-to-start queue delay is only **0.05–1.59 ms**; priority could still affect CPU progress, but the trace isolates a much larger serial substage. **Falsifier:** a same-input priority A/B materially reduces `sign_edge_distances` or the shape-stage wall time. [Task priority and queue delay](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-2.trace.jsonl:23>)
|
||
|
||
**[TRACE]** The headless L84/L86/L87 shape timings show that the compiler can finish in roughly **0.25–0.4 s** for those runs, but they do not falsify the R43 finding: R43’s SW camera hits the SurfaceWorld region and triggers the measured 10.9M serial sign corrections. **[INFERENCE]** A headless trace with the same request bounds, spawn, and repair mode would be the clean comparison. **Falsifier:** that matched headless run also takes about 2 s in `sign_edge_distances`. [L84](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux84/REPORT.md>), [L86](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux86/REPORT.md>), [L87](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux87/REPORT.md>) |