wip(assembler): round S14 -- 4-way column cache + memoized MC gradients (output unchanged)
Worker-local XY column cache uses deterministic 4-way sets at LOD3-8: LOD4 misses 8,224 -> 1,437, conflicts 7,407 -> 0 (direct-map control: 6.62 s / 43.5 worker-s vs 4.24 s / 21.7). Exact LOD0 lattice gradients memoized per tile: MC-exclusive 242 -> 201 ns/sample, two-pass loop unchanged. Hashes identical, no recipe bump. Primary cold trace 4.24 s full set, ring 0.45 s, 75/75 at 40 m/s; a repeat ran uniformly ~40% slower on every LOD (machine contention suspected); tick p95 to re-check on an idle machine. CVars voxel.CoreColumnCacheDirectMapped / voxel.CoreMCGradientMemoization. Report: Standalone/Research/WorldAssemblerM3/Round18. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
bd5e38594f
commit
ec2afe9c93
11 files changed
+769
-50
No files matched your search
@@ -0,0 +1,340 @@
|
||||
# World Assembler S14 — Round 18
|
||||
|
||||
## Decision
|
||||
|
||||
Shipped two output-preserving changes justified by the measurements:
|
||||
|
||||
1. Keep the 65,536-entry XY column cache worker-local. Use the old direct-map route at LOD0–2,
|
||||
where conflict counts are low, and deterministic four-way sets at LOD3–8. The LOD4 miss spike
|
||||
falls from 8,224 to 1,437, with conflict misses falling from 7,407 to zero.
|
||||
2. Memoize exact step-1 ShapeWorld MC grid gradients per worker and tile. The MC two-pass loop,
|
||||
density grid, halo, central differences, and output values stay intact. LOD0 MC-exclusive cost
|
||||
falls from 241.87 to 201.48 ns/sample in the corrected-source audit; the original S13 figure was
|
||||
243.40 ns/sample.
|
||||
|
||||
No shared XY page was built: cross-worker repeats show opportunity, but no measured page-cache A/B
|
||||
shows a net cold-path win after the cache fix. The primary cold trace used 21.722 worker-seconds against
|
||||
the 28.8 s target. Output hashes remain unchanged, so the recipe stays `MarchingCubesV1`; no recipe
|
||||
bump or matched captures were required.
|
||||
|
||||
## 1. What the 243 ns/sample contains
|
||||
|
||||
The S13 “MC-exclusive” timer excludes MC column evaluation; it does **not** mean “triangle loop
|
||||
only.” For LOD0, the corrected-source eight-tile audit measured 8.638 ms MC-exclusive plus 3.852 ms
|
||||
MC column evaluation at the tuned setting. Each LOD0 tile has 35³ = 42,875 density samples. The
|
||||
exclusive result is 201.48 ns/sample. The cell loop itself is only one part of it.
|
||||
|
||||
In the sampled stage audit, tuned LOD0 p95 was: density grid 8.971 ms (7.071 ms excluding column
|
||||
evaluation), cell classification 0.143 ms, grid-gradient normals 1.036 ms, edge interpolation
|
||||
0.080 ms, vertex dedup/stream 0.545 ms, and about 2.168 ms of unassigned remainder. The stage
|
||||
profiler samples one in eight cells; these are independently calculated p95 values and do not add
|
||||
to a measured total. Its `Other`/setup-finalization and unassigned-residual fields are computed
|
||||
remainder buckets from different inclusive/exclusive timers, not separately isolated setup or
|
||||
allocator timers.
|
||||
|
||||
The 164.93 ns/sample grid remainder is not a standalone `height - z` timer. Every lattice sample
|
||||
still enters the exact `Heightfield2D::point` path: fixed-coordinate conversion, recipe/plan lookup,
|
||||
the worker-local XY cache probe, the Z-dependent ground/cap composition, and any applicable exact
|
||||
feature/edit checks. Column generation itself is counted separately: LOD0 records 44,100 field
|
||||
calls, 2,244 cache misses (about 94.9% hits), and 89.89 ns/sample of column computation. The audit
|
||||
does not split cache-hit lookup from Z composition and call overhead. Those Z/feature checks cannot
|
||||
all move to one XY-column operation. The MC gradient work can be shared per lattice point and is
|
||||
now memoized exactly; edge interpolation is already limited to crossed edges and the vertex map
|
||||
deduplicates shared edge vertices. Material and allocation have no separate timers; the mesher's
|
||||
thread-local grids and dedup map retain capacity between tiles.
|
||||
|
||||
The MC route still uses the protected two-pass loop: pass one rejects empty cells from the eight
|
||||
cached corners; pass two computes positions, gradients, and emitted triangles only for surface
|
||||
cells. Classification is per cell; exact gradients are reused per lattice point; interpolation and
|
||||
deduplication are limited to crossed edges and their shared vertex keys. The stage measurements
|
||||
place classification in the first pass and interpolation plus dedup/stream in the second.
|
||||
Material/ground-cap grouping and vertex attributes are folded into
|
||||
vertex creation and streaming; material work has no separate timer. The 35 edge-midpoint density
|
||||
probes are negligible beside the gradient fallback calls.
|
||||
|
||||
| LOD | Density grid incl. | Grid excl. columns | Cell classification | Gradient normals | Edge interpolation | Dedup/stream | Unassigned residual |
|
||||
|---:|---:|---:|---:|---:|---:|---:|---:|
|
||||
| 0 | 210.11→209.22 | 168.04→164.93 | 3.28→3.32 | 65.10→24.16 | 1.91→1.86 | 12.96→12.72 | 50.40→50.56 |
|
||||
| 1 | 163.74→164.91 | 163.74→164.91 | 3.82→3.55 | 4.20→4.01 | 2.14→2.10 | 13.47→13.56 | 54.77→55.06 |
|
||||
| 2 | 390.55→395.47 | 0.00→0.00 | 2.84→2.89 | 11.62→11.51 | 6.14→5.47 | 68.70→69.15 | 277.12→306.20 |
|
||||
| 3 | 777.21→437.15 | 120.00→131.99 | 3.15→2.97 | 15.37→15.37 | 6.77→6.25 | 604.40→407.99 | 46.97→110.89 |
|
||||
| 4 | 4,603.98→425.25 | 210.50→178.79 | 2.92→3.32 | 10.15→10.96 | 5.60→5.48 | 565.21→309.90 | 95.44→109.50 |
|
||||
| 5 | 385.90→434.09 | 135.75→155.07 | 3.02→3.48 | 5.13→7.00 | 1.78→3.50 | 155.02→38.26 | 96.38→137.65 |
|
||||
| 6 | 366.38→371.92 | 88.76→101.46 | 2.97→3.09 | 18.66→18.11 | 9.72→8.39 | 431.20→185.07 | 124.84→171.70 |
|
||||
| 7 | 361.29→447.14 | 115.03→102.64 | 3.13→2.99 | 20.47→17.75 | 9.69→8.84 | 443.10→239.22 | 99.92→254.21 |
|
||||
| 8 | 367.98→377.58 | 95.55→96.05 | 4.05→3.05 | 14.90→19.08 | 7.48→7.92 | 513.15→213.89 | 159.02→234.19 |
|
||||
|
||||
All stage values are p95 **ns/sample**, before→after. “Before” is this build with the direct-map
|
||||
cache and gradient memo off (`1/0`); “after” is this build's tuned default (`0/1`). Each side measured eight
|
||||
tiles per LOD, with `hashes_identical=1`. LOD0/1 use 42,875 samples; LOD2–8 use 6,859. Large
|
||||
variation in dedup/stream and residual is content/triangle-count and sampling noise, not a new
|
||||
approximation. The last column is the commandlet's unassigned-residual bucket; the separately
|
||||
reported setup-finalization field is also computed as a remainder and is not an allocator timer.
|
||||
These warmed-route stage probes explain the hot path; the cold production timings are the
|
||||
fresh-process trace in section 4.
|
||||
|
||||
| LOD | Candidate tile p95 ms | MC column p95 ms | MC-exclusive p95 ms / ns per sample | Column misses / conflicts |
|
||||
|---:|---:|---:|---:|---:|
|
||||
| 0 | 14.079→12.492 | 3.777→3.852 | 10.370→8.638 / 241.87→201.48 | 2,244/33→2,244/33 |
|
||||
| 1 | 9.824→9.842 | 4.187→4.197 | 7.183→7.307 / 167.53→170.43 | 2,289/28→2,289/28 |
|
||||
| 2 | 4.715→4.709 | 3.080→3.066 | 1.606→1.616 / 281.61→282.71 | 681/4→681/4 |
|
||||
| 3 | 6.945→5.393 | 4.016→2.477 | 2.917→2.903 / 425.28→423.27 | 1,634/1,119→574/0 |
|
||||
| 4 | 36.854→9.227 | 30.216→2.257 | 2.970→2.946 / 432.93→429.54 | 8,224/7,407→1,437/0 |
|
||||
| 5 | 11.055→9.129 | 3.029→2.278 | 1.279→1.269 / 186.43→184.98 | 1,916/1,476→1,351/0 |
|
||||
| 6 | 30.703→26.872 | 5.148→3.841 | 2.142→2.000 / 312.23→291.57 | 6,403/2,094→5,570/1 |
|
||||
| 7 | 20.831→15.390 | 4.725→3.460 | 2.411→2.689 / 351.52→391.97 | 3,472/2,926→1,822/0 |
|
||||
| 8 | 14.948→9.829 | 5.715→3.358 | 2.534→2.770 / 369.38→403.82 | 2,708/2,215→1,162/0 |
|
||||
|
||||
For LOD0 specifically, the S13 audit row was 14.160 ms candidate, 3.708 ms column evaluation,
|
||||
10.436 ms MC-exclusive, and 243.40 ns/sample. The tuned corrected-source 35³ route is 12.492 ms
|
||||
candidate and 8.638 ms MC-exclusive. Subtracting the measured density-grid p95 from candidate p95
|
||||
leaves about 3.52 ms for the remaining work (about 82 ns/sample); the independently sampled stage
|
||||
subtotal is about 3.97 ms (about 93 ns/sample). This is the measured in-world estimate for the
|
||||
MC/classification/normal/interpolation/streaming work after density-grid evaluation, not a direct
|
||||
pre-filled-grid benchmark. Treat the p95 subtraction as an estimate, not an additive percentile.
|
||||
|
||||
Gradient memoization reduces LOD0 fallback density probes from 11,474 to 3,018 per sampled p95
|
||||
(−73.7%) and normal cost from 65.10 to 24.16 ns/sample. It records 5,610 memo hits. The memo stores
|
||||
the exact central-difference vector at each grid lattice point, is worker-local, and resets its
|
||||
validity bytes per tile. The existing grid and per-worker capacities are reused. No material
|
||||
approximation or altered gradient arithmetic is involved.
|
||||
|
||||
## 2. Why LOD4 had the cache spike
|
||||
|
||||
The old cache already holds 65,536 `HeightfieldPointSample`s per worker, but its direct-map index
|
||||
uses pointer identity and coordinate bits. Coarse LOD coordinates share sparse low-bit patterns;
|
||||
the LOD4 16-voxel cap grid interleaves different XY probes with the MC grid and its halo/normal
|
||||
lookups. The measured direct-map conflict count (7,407 of 8,224 misses) shows this is mostly
|
||||
eviction, rather than 8,224 necessary unique columns. The audit did not tag every miss by probe
|
||||
source, so the individual halo-versus-cap contribution is not claimed.
|
||||
|
||||
The new default keeps the same total entries and exact key verification. Its avalanched coordinate
|
||||
hash selects one of 16,384 four-way sets; deterministic round-robin replacement only changes
|
||||
residency, never values. Exact recipe/plan identities, content hashes, and XY coordinates are
|
||||
checked on every hit, so fill order cannot affect output. LOD0–2 keep the fast original path because
|
||||
they have only 33, 28, and 4 direct-map conflict misses in the audit. LOD6 remains at 5,570 misses
|
||||
but only one conflict, showing that its remaining cost comes largely from its larger real XY
|
||||
footprint and connector-shell work, not direct-map collision.
|
||||
|
||||
`voxel.CoreColumnCacheDirectMapped=1` is the direct-map negative control and was read back as `1`
|
||||
in the trace. With gradient memo still on, the initial set took 6.624 s and 43.493 worker-seconds;
|
||||
LOD4 used 11.071 worker-seconds. The tuned default took 4.238 s and 21.722 worker-seconds, with
|
||||
LOD4 at 1.862 worker-seconds. The isolated audit also reports the per-LOD miss deltas above.
|
||||
|
||||
The separate memo negative control was `voxel.CoreMCGradientMemoization=0` with the four-way
|
||||
column cache still enabled; both values were read back as `0/0`. It took 4.908 s and 27.609
|
||||
worker-seconds, versus 4.238 s and 21.722 s at the `0/1` default. Its 3×3 support ring was 0.602 s
|
||||
versus 0.447 s, and LOD0 last apply was 1.453 s versus 1.171 s. This cold-path A/B supports keeping
|
||||
the exact gradient memo. The direct-map control is `1/1` and isolates the cache behavior; the memo
|
||||
control is `0/0` and isolates the gradient behavior.
|
||||
|
||||
## 3. Shared XY pages
|
||||
|
||||
The corrected-source Standalone W8 overlap capture counted 281,910 cross-worker neighboring
|
||||
duplicate columns at LOD0 and 123,803 at LOD4. Against Round17 (276,658 and 202,684), LOD0 is up
|
||||
about 2%, while LOD4 is down about 39% after fixing intra-worker cache conflicts. The counters are
|
||||
schedule-dependent work counts, not world output. Multiplying those counts by the current stage
|
||||
audit's p95 column-time-per-miss ratios gives a rough estimate of 0.68 worker-seconds across the
|
||||
LOD0/LOD4 repeats if each repeat avoided a recomputation and the shared lookup had zero cost. That
|
||||
is about 3.1% of the measured 21.722 worker-seconds, before synchronization and memory costs. This
|
||||
is an estimate, not a cold-path A/B win measurement.
|
||||
|
||||
After the four-way change, the remaining upper bound is too small to justify adding an unmeasured
|
||||
synchronized page in this round. It would also add ownership/lifetime and bounded-memory work under
|
||||
the S8 rules. The page was therefore not built. Existing immutable region pages and their S8
|
||||
lifetime are unchanged; no new page lifetime needs proving.
|
||||
|
||||
## 4. Cold 40 m/s trace
|
||||
|
||||
Fresh BuildHost process, 25 cm SurfaceWorld, 40 m/s along +Y, background worker cap 1, ready queue
|
||||
8, dynamic reserve, collision lookahead 1, `CoreColumnCacheDirectMapped=0`, and
|
||||
`CoreMCGradientMemoization=1`. The `worker_backend_config` JSONL row reads back all these controls.
|
||||
Round17 and Round18 use the same trace command and post-`BeginPlay` `elapsed_s` origin. In this run
|
||||
`elapsed_s=4.238189`; raw trace `t_s` is 4.320372. Trace `t_s` begins 0.082022 s before the
|
||||
end-of-BeginPlay origin. The 3×3 walkable support ring is measured at its first ready gate using
|
||||
that same origin. S12's actor report uses a different clock origin; its comparisons are stated as
|
||||
references, not clock-normalized samples.
|
||||
|
||||
| Metric | Round17 S13 | S14 primary | S14 fresh repeat |
|
||||
|---|---:|---:|---:|
|
||||
| Initial set | 2,578 tiles / 4.825 s | 2,578 / 4.238 s | 2,578 / 5.151 s |
|
||||
| Initial-set worker seconds | 28.760 | 21.722 | 29.969 |
|
||||
| 3×3 walkable support ring | 0.510 s | 0.447 s | 0.971 s |
|
||||
| LOD0 last worker end | 1.131 s | 1.156 s | 1.524 s |
|
||||
| LOD0 last apply | 1.146 s | 1.171 s | 1.532 s |
|
||||
| 40 m/s moving readiness | 75/75 ready | 75/75 ready | 57/57 logged samples ready |
|
||||
| Spawn `UWorld::Tick` p95/max | 3.133 / 5.426 ms | 4.200 / 5.571 ms | 4.601 / 6.682 ms |
|
||||
| Walk `UWorld::Tick` p95/max | 30.314 / 43.142 ms | 32.218 / 45.720 ms | 33.986 / 41.654 ms |
|
||||
|
||||
| Initial-set LOD | Tiles | S14 primary worker s | S14 repeat worker s |
|
||||
|---:|---:|---:|---:|
|
||||
| 0 | 512 | 4.520 | 6.319 |
|
||||
| 1 | 448 | 4.696 | 6.304 |
|
||||
| 2 | 320 | 0.870 | 1.241 |
|
||||
| 3 | 272 | 0.829 | 1.193 |
|
||||
| 4 | 272 | 1.862 | 2.634 |
|
||||
| 5 | 208 | 1.478 | 2.121 |
|
||||
| 6 | 144 | 2.179 | 3.168 |
|
||||
| 7 | 96 | 1.723 | 2.206 |
|
||||
| 8 | 306 | 3.565 | 4.782 |
|
||||
| **Total** | **2,578** | **21.722** | **29.969** |
|
||||
|
||||
The same-build LOD0 candidate-tile p95 fell 11.3% (14.079 to 12.492 ms). In the cold trace, LOD0
|
||||
worker time fell 3.3% (4.672 to 4.520 s across 512 tiles, or 9.13 to 8.83 ms per tile).
|
||||
|
||||
The primary cold trace meets the 4.8 s full-set, 28.8 worker-second, and 0.51 s support-ring
|
||||
targets, with all 75 moving samples ready. LOD0 is materially cheaper per tile. LOD0 last apply is
|
||||
81 ms over the ~1.09 s target. I made one more fresh default trace to check the tick regression;
|
||||
the same binary and `0/1` CVar readback passed the commandlet but took 5.151 s and 29.969
|
||||
worker-seconds for all 2,578 tiles, 0.971 s for the support ring, and 1.532 s for the last LOD0
|
||||
apply. Peak private memory was 3.29 GiB. Its spawn tick was 4.601/6.682 ms and walking tick was
|
||||
33.986/41.654 ms p95/max; all 57 logged 40 m/s streaming samples stayed walkable-ready. Thus the
|
||||
full-set, worker-second, support-ring, and LOD0 apply targets pass in the primary run but fail on
|
||||
this repeat. Spawn tick p95/max is worse than S13 and matched S12 in both runs; walking p95 is
|
||||
worse than both in both runs. The first-run walking max is worse than both references; the repeat
|
||||
is worse than S12 but below S13. The strict no-worse tick goal therefore fails. I kept the S13
|
||||
worker cap at 1; the measurements do not justify raising it.
|
||||
|
||||
## 5. Quality and determinism
|
||||
|
||||
- BuildHost W1/W8/W16 stable: density/mesh/payload/topology
|
||||
`0cd2a1a4152ee4aa / a06243aee16b65d5 / c700162935c262d7 / 0af901aa42b452bc`.
|
||||
- Standalone W1/W8/W12, fresh `--force-generate`: whole-view 2,553-tile hashes all match:
|
||||
`c10697a8f48380c7 / e75c9119a1498cd5 / 49a9a8d1835a6c8c / edcb23288b5e8724`.
|
||||
Full-detail 960-tile hashes also match:
|
||||
`0ee0579bd15cbbe4 / 32e5d4964d610fee / 1932b96ee4b1d910 / 69743c6bad3447dc`.
|
||||
- Core-off at 12.5 cm: `VOXELFORGE_CORE_OFF_LEGACY_PASS`.
|
||||
- M2 Hybrid V1 and V2 at 25 cm: five analytic fixtures and borders passed.
|
||||
- SurfaceWorld at 25 cm: BuildHost W1/W8/W16, geometry scale and height agreement, carve/fill,
|
||||
native/bridge, and collision checks passed.
|
||||
- S3 far-horizon agreement: max 0.0427 cm against 2 cm.
|
||||
- S4 far-cap agreement: 128 shared points, max 0.0504 cm against 2 cm; negative control detected.
|
||||
Cap rays: 1,584/1,584 (100%), no misses.
|
||||
- FloatingIslands at 25 cm: W1/W8/W16 stable:
|
||||
`4dcfb37585d7d986 / f14f76fbf065c6ed / 53035c45fd1a082e / 23550100654a4ec3`;
|
||||
island and span contacts, anchors, carve/fill passed; water remained fixed.
|
||||
|
||||
No density, mesh, topology, payload, or collision output changed. No recipe bump or paired near/far
|
||||
captures are needed.
|
||||
|
||||
## 6. Build, commands, and evidence
|
||||
|
||||
Builds (Normal priority, maximum 12 parallel workers):
|
||||
|
||||
```powershell
|
||||
.\Tools\BuildVoxelForgeCoreHost.ps1 -MaxParallelActions 12 -TimeoutSeconds 900
|
||||
.\Standalone\Build.ps1 -Target All -CompileWorkers 12 -BuildPriority Normal
|
||||
```
|
||||
|
||||
BuildHost feature-stage controls:
|
||||
|
||||
```powershell
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -SharedFeatureAuditOnly -CoreMCStageAudit -CoreColumnCacheDirectMapped 1 -CoreMCGradientMemoization 0 -CoreVoxelSizeCm 25 -TimeoutSeconds 900
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -SharedFeatureAuditOnly -CoreMCStageAudit -CoreColumnCacheDirectMapped 0 -CoreMCGradientMemoization 1 -CoreVoxelSizeCm 25 -TimeoutSeconds 900
|
||||
```
|
||||
|
||||
Cold stream command:
|
||||
|
||||
```powershell
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -StreamingTraceOnly -StreamingOrder Legacy -NearReserveMode Dynamic -CoreVoxelSizeCm 25 -StreamingCollisionLookahead 1 -TestMoveDirection '0,1,0' -CoreRegionConcurrentAdmission 1 -StreamingResultBacklogCap 256 -TestMoveSpeedCmPerSecond 4000 -StreamingReadyQueueDepth 8 -StreamingBackgroundWorkerCap 1 -CoreColumnCacheDirectMapped 0 -CoreMCGradientMemoization 1 -TimeoutSeconds 900
|
||||
```
|
||||
|
||||
The cold-path negative controls held every other argument fixed; the trace JSONL recorded the CVar
|
||||
readbacks (`0/0` for memo-off, `1/1` for direct-map):
|
||||
|
||||
```powershell
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -StreamingTraceOnly -StreamingOrder Legacy -NearReserveMode Dynamic -CoreVoxelSizeCm 25 -StreamingCollisionLookahead 1 -TestMoveDirection '0,1,0' -CoreRegionConcurrentAdmission 1 -StreamingResultBacklogCap 256 -TestMoveSpeedCmPerSecond 4000 -StreamingReadyQueueDepth 8 -StreamingBackgroundWorkerCap 1 -CoreColumnCacheDirectMapped 0 -CoreMCGradientMemoization 0 -TimeoutSeconds 900
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -StreamingTraceOnly -StreamingOrder Legacy -NearReserveMode Dynamic -CoreVoxelSizeCm 25 -StreamingCollisionLookahead 1 -TestMoveDirection '0,1,0' -CoreRegionConcurrentAdmission 1 -StreamingResultBacklogCap 256 -TestMoveSpeedCmPerSecond 4000 -StreamingReadyQueueDepth 8 -StreamingBackgroundWorkerCap 1 -CoreColumnCacheDirectMapped 1 -CoreMCGradientMemoization 1 -TimeoutSeconds 900
|
||||
```
|
||||
|
||||
Standalone processes were sequential, Normal priority, 12-CPU affinity, and used `--force-generate`:
|
||||
|
||||
```powershell
|
||||
.\Standalone\bin\VoxelForgeCoreStandalone.exe --workers=1 --world-assembler-prototype --stream-benchmark --stream-pipeline --stream-hash --force-generate --clip-radius=3 --max-clip-level=8 --camera=0,-35,-487.94,0,-22 --far-horizon-lod8-step=0 --process-priority=Normal --process-affinity=4095 --frame-limit=60
|
||||
.\Standalone\bin\VoxelForgeCoreStandalone.exe --workers=8 --world-assembler-prototype --stream-benchmark --stream-pipeline --stream-hash --profile-column-overlap --force-generate --clip-radius=3 --max-clip-level=8 --camera=0,-35,-487.94,0,-22 --far-horizon-lod8-step=0 --process-priority=Normal --process-affinity=4095 --frame-limit=60
|
||||
.\Standalone\bin\VoxelForgeCoreStandalone.exe --workers=12 --world-assembler-prototype --stream-benchmark --stream-pipeline --stream-hash --force-generate --clip-radius=3 --max-clip-level=8 --camera=0,-35,-487.94,0,-22 --far-horizon-lod8-step=0 --process-priority=Normal --process-affinity=4095 --frame-limit=60
|
||||
```
|
||||
|
||||
Other BuildHost gate commands:
|
||||
|
||||
```powershell
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -CoreOffTest -CoreVoxelSizeCm 12.5 -TimeoutSeconds 900
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -HybridFixturesOnly -CoreMesherRecipe WorldAssemblerHybridV1 -CoreVoxelSizeCm 25 -TimeoutSeconds 900
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -HybridFixturesOnly -CoreMesherRecipe WorldAssemblerHybridV2 -CoreVoxelSizeCm 25 -TimeoutSeconds 900
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -CoreVoxelSizeCm 25 -TimeoutSeconds 900
|
||||
.\Tools\TestVoxelForgeCoreWorldHost.ps1 -FloatingIslandsOnly -CoreVoxelSizeCm 25 -TimeoutSeconds 900
|
||||
```
|
||||
|
||||
Measured binaries and SHA-256:
|
||||
|
||||
| Binary | SHA-256 |
|
||||
|---|---|
|
||||
| UE `UnrealEditor-Cmd.exe` | `ECCE9996191F7F7E69B3D104EECDD0E678AE69176FDCCD79828C3E75A0654D6D` |
|
||||
| BuildHost `UnrealEditor-VoxelForge.dll` | `4E55A38547B96221562AEC84D61B0FFC7E455E21420C51E14D2BEACA88217A07` |
|
||||
| BuildHost `UnrealEditor-VoxelForgeCore.dll` | `1F34F96208FC0E0A72CE2CE80014EBFB110C29C8333053A90735DF9C7BEE7949` |
|
||||
| BuildHost `UnrealEditor-VoxelForgeEditor.dll` | `9B35350BBA3E7CE4F8D8DA617C216B21CB4CF9869FE5903FD84AAC6906B8187B` |
|
||||
| Standalone `VoxelForgeCoreStandalone.exe` | `91D29D8BA421304F085BFAB4CCE5EC9DDD32C40BE13F15E118E0DC9606D21B84` |
|
||||
|
||||
Full logs, traces, and Standalone stdout/stderr are under `Saved/BuildHost/`; the current 40 m/s
|
||||
trace files are in `Saved/BuildHost/HostProject/Plugins/VoxelForge/Saved/CoreWorldValidation/Logs/`.
|
||||
The fresh repeat uses the same CVar-derived JSONL path as the primary trace, so its JSONL is the
|
||||
current trace; the faster primary run's engine log summary is retained in that Logs directory as
|
||||
`CoreWorldValidation-owner_surface_stream_trace_only_applyboost_default_bgcap_1_readyq_8_legacy_order_colcache_4way_gradientmemo_on_nearreserve_dynamic_trace_move_4000_lookahead_1_dir_0_1_0_region_1_backlog_256-backup-2026.10.19-15.44.14.log`.
|
||||
Per-run Standalone command records and logs are in `Saved/BuildHost/WorldAssemblerM3/Round18/Standalone/`.
|
||||
|
||||
## 7. Failed probes, retries, and safety review
|
||||
|
||||
- `-coremcstageaudit=1` was ignored by Unreal’s boolean argument parser; the audit was repeated
|
||||
with the bare `-coremcstageaudit` flag.
|
||||
- An early direct-map control did not read back `1`, and an early audit binary did not log either
|
||||
new CVar. Those measurements were rejected. I added the S11-style explicit BeginPlay parse and
|
||||
trace readback, rebuilt BuildHost, then reran the direct/off baseline and tuned audit; the JSONL
|
||||
readbacks are `1/0` and `0/1` respectively.
|
||||
- The first corrected shared-audit command was rejected by a harness guard before launch because
|
||||
it treated audit CVars as trace-only controls. The guard now allows them in shared-feature
|
||||
audits; the rerun passed.
|
||||
- The first W8 Standalone wrapper could not resolve its process-local memory helper type. That
|
||||
run exited 0 and its process peak was 0.70 GiB, but its free-memory preflight was invalid. I
|
||||
repeated W8 with the helper defined in that process: free-before 17.12 GiB, peak 0.71 GiB,
|
||||
exit 0, and the whole-view hashes matched W1/W12.
|
||||
- `Get-CimInstance` was denied and `Get-Counter` lacked the requested counter. I used
|
||||
`GlobalMemoryStatusEx` instead; the initial available-memory reading was 15.85 GiB. BuildHost
|
||||
scripts also enforce the 4 GiB preflight, Normal priority, 12-CPU affinity, 8 GiB process cap,
|
||||
and 900 s timeout.
|
||||
- Standalone build printed that `vswhere.exe` was not recognized and emitted existing
|
||||
`VoxelStrateManager.cpp` C4838 narrowing warnings, but built both targets and exited successfully.
|
||||
- BuildHost UBT passed on its first attempt; the 18 Core link shims passed link-safety inspection.
|
||||
No `0xC0000142` occurred. No new `UECC-*` folder appeared (the only matching folder predates
|
||||
this round, from 2026-09-17).
|
||||
- Final diff review made the gradient memo's per-tile validity reset explicit by clearing every
|
||||
validity byte after resizing the scratch array. Both targets were rebuilt and the corrected-source
|
||||
stage, determinism, quality, and cold-trace gates were rerun; hashes stayed identical.
|
||||
|
||||
Diff review: no edits to `Epoch`, either MPSC queue, `EndPlay` draining, worker shutdown checks,
|
||||
`ModsLock`, immutable region-page lifetime, or game-thread UObject/RMC mutation. The new cache and
|
||||
gradient scratch remain thread-local. The readable RealtimeMeshComponent source was not modified.
|
||||
No owner project, editor, asset, generated header, `Binaries/`, or `Intermediate/` source was edited.
|
||||
No commit, push, or stash.
|
||||
|
||||
## 8. Files and compile spots
|
||||
|
||||
No new source file was added.
|
||||
|
||||
| Changed file | Likely compile/build spot |
|
||||
|---|---|
|
||||
| `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h`, `Standalone/Core/src/VoxelForgeCore.cpp`, `Standalone/Core/src/WorldAssemblerInternal.h` | Standalone Core and BuildHost `VoxelForgeCore` |
|
||||
| `Standalone/Source/VoxelForge/Public/VoxelMarchingCubesMesher.h`, `Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp` | Standalone executable and BuildHost `VoxelForge` runtime |
|
||||
| `Source/VoxelForge/Private/VoxelWorld.cpp` | BuildHost `VoxelForge` runtime |
|
||||
| `Source/VoxelForgeEditor/Private/VoxelForgeExploreCommandlet.cpp` | BuildHost `VoxelForgeEditor` |
|
||||
| `Tools/TestVoxelForgeCoreWorldHost.ps1` | BuildHost validation harness; no compile |
|
||||
| `ARCHITECTURE.md`, `CODEMAP.md` | Documentation; no compile |
|
||||
|
||||
### Dialogue
|
||||
|
||||
**Owner:** What is inside the LOD0 MC-exclusive cost, why does LOD4 miss, and is a shared page worth it?
|
||||
|
||||
**Codex:** LOD0’s dominant measured MC-exclusive stage is density-grid evaluation excluding XY
|
||||
column work (about 165 ns/sample), followed by grid-gradient normals (24 ns/sample after exact
|
||||
memoization). The cache counters show LOD4’s direct-map spike was chiefly conflicts; four-way sets
|
||||
remove those while keeping exact samples. Cross-worker repeats remain, but no shared-page A/B
|
||||
measured a net cold-path win, so I left the S8 page lifetime unchanged.
|
||||
Reference in new issue
Block a user