From 83a0e4d85cb7f3e447ad2ef31010d6a626eb82d9 Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Sat, 12 Sep 2026 22:02:53 +0200 Subject: [PATCH] measure(classifier): outer classifier is net-negative in game; nested 3.5x IS real Three-mode outer-classifier A/B on the headless game path, nested refinement off in all modes, clean and diagnostics off. Runs made by the forked Codex session; the table was assembled and checked by me from its logs (Saved/OuterABMode*_20260912.log, OuterABMove*Headless_20260912.log). static ready p95 mode0 182.4-182.7 mode1 189.7-194.8 mode2 190.0-194.7 ms gen p95 mode0 124.9-127.0 mode1 139.1-140.6 mode2 140.3-141.3 ms worker CPU mode0 184.9-193.5 mode1 201.2-202.3 mode2 201.2-201.3 s density mode0 18.05M mode1 21.89M mode2 21.89M moving ready p95 mode0 198.9 mode1 208.0 mode2 210.7 ms density mode0 57.7M mode1 69.6M mode2 69.6M The outer classifier costs more than it saves: with it removed (mode 0), every latency figure improves and density calls drop by about 18%. Mode 0 also cannot remove geometry, because it skips nothing. Mode 2 (reuse the validation samples as the mesher's core grid) recorded 0 reuse tiles in every run. That is by design, not a bug: the grid is only reused when validation DISPROVES a uniform verdict, and it disproved none. Mixed tiles, which are the ones that need a grid, never run validation at all. Recommendation recorded in WORK-NEXT.md, pending the owner: default the outer classifier mode to 0. The code default is NOT changed in this commit. CORRECTION to f204413, whose message says the nested classifier's 3.5x could not be reproduced. That was my error. I passed the streaming console variable -voxel.UseBlockEarlyOut=1 to the export commandlet, which reads its own -blockearlyout= argument (VoxelForgeExploreCommandlet.cpp:381, :1093), so both of my runs had nested refinement off. Re-run with the right flag: -blockearlyout=0 0.553 / 0.572 s -blockearlyout=1 2.036 / 2.060 s 3.6x, geometry SHA-256 b3e5f4c3..9b377 identical The 3.5x was real. Turning nested refinement off in streaming (f204413) was worth it, and Sol's reading of the table was right where mine was wrong. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01VZS94UH8bSsBeg5sZaxe2Y --- WORK-NEXT.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/WORK-NEXT.md b/WORK-NEXT.md index 9df69a2..8e8feee 100644 --- a/WORK-NEXT.md +++ b/WORK-NEXT.md @@ -107,6 +107,34 @@ deliberate cache probe are removed. The proof classifier remains; item 4 is stil --- +## Outer-classifier A/B — measured 2026-09-12 (nested refinement OFF in every mode) + +Clean, diagnostics off, headless game path. Static = 343 LOD0 samples, two runs per mode; moving = +160 m at 8 m/s, 1,274 LOD0 samples. Density calls = validation + mesher. + +| mode | ready p95 static | gen p95 static | worker CPU static | density calls static | ready p95 moving | gen p95 moving | density calls moving | +|---|---:|---:|---:|---:|---:|---:|---:| +| 0 no outer classifier | **182.4-182.7 ms** | **124.9-127.0 ms** | **184.9-193.5 s** | **18.05 M** | **198.9 ms** | **129.9 ms** | **57.7 M** | +| 1 current (validate, discard) | 189.7-194.8 ms | 139.1-140.6 ms | 201.2-202.3 s | 21.89 M | 208.0 ms | 143.4 ms | 69.6 M | +| 2 validation-grid reuse | 190.0-194.7 ms | 140.3-141.3 ms | 201.2-201.3 s | 21.89 M | 210.7 ms | 143.3 ms | 69.6 M | + +**Verdict: the outer classifier is net-negative on the game path.** Mode 0 is better on every latency +figure and does ~18% fewer density calls. It cannot remove geometry, since it skips nothing. + +**Mode 2 cannot win as designed.** It reuses the validation grid only when a uniform verdict is +*disproved* (`VoxelWorld.cpp` ~4012), and validation disproved none: 0 reuse tiles in every run. Mixed +tiles, the ones that actually need a grid, never run validation, so there is nothing to reuse. + +**Recommendation, pending the owner:** set `GVoxelForgeOuterClassifierMode` default to 0. It stays +switchable by `voxel.OuterClassifierMode`. + +⚠️ **Correction to `f204413`.** Its message says the nested classifier's 3.5x "cannot be reproduced". +That was my measurement error: I passed `-voxel.UseBlockEarlyOut=1` (the STREAMING console variable) +to the export commandlet, which reads its own `-blockearlyout=` argument, so both of my runs had +nested refinement off. Re-run with the right flag: `-blockearlyout=0` 0.553 / 0.572 s, +`-blockearlyout=1` 2.036 / 2.060 s, which is **3.6x**, with byte-identical geometry. The 3.5x was real, +and disabling nested refinement in streaming (`f204413`) was worth it. + ### Open design questions for the owner - All five strate slots resolve to `DA_Strate3`. Intended? - Should a composer roll be allowed to overwrite an explicitly authored value?