perf(streaming): item 3 bought nothing, item 5 removed dead weight -- both worth knowing

Two WORK-NEXT items, one null result and one confirmed removal. Item 4 untouched.

ITEM 3 -- CANCEL OBSOLETE WORK AND PRIORITISE THE FLOOR: NULL RESULT
Clean -nullrhi, diagnostics off, 800 cm/s, 200 m of travel:

                          before            after
  request->ready p95      0.369117 s        0.367612 s
  queue wait p95          0.066949 s        0.064483 s
  generation p95          0.287926 s        0.283642 s
  p95 travel distance     2.952938 m        2.940894 m
  obsolete aborts                 0                12

Flat. Aborting obsolete tiles, sorting from the true pawn position and prioritising the
occupied/next tile changed request-to-ready by 0.4%.

⭐ AND THE NULL RESULT IS ITSELF THE FINDING. Look at the split: queue wait is 65 ms of a
368 ms p95; generation is 284 ms. **The queue was never the problem, so reordering it
cannot help.** Only 12 tiles in a 200 m run were obsolete enough to abort. The floor is
late because generation is slow, not because work is badly ordered -- item 3 establishes
that by exclusion, which is worth more than the 0.4%.

The machinery is kept: it is correct, it costs nothing, and it will matter once
generation is fast enough for ordering to be the binding constraint.

ITEM 5 -- VERDICT CACHE REMOVED. It was pure overhead.
Clean moving-session audit:

  outer  calls/probes/hits    2,109 / 2,109 / 0
  nested calls/probes/hits   19,904 / 19,904 / 0
  enclosing hits                              0
  stores 15,877, evictions 15,365

⇒ It stored 15,877 proofs, evicted 15,365 of them, and hit ZERO times. A moving player
visits unique regions; the cache was filling and thrashing a 512-entry table under a
global lock for no benefit. Same-binary A/B: request p95 0.367645 vs 0.365978,
generation p95 0.285559 vs 0.285992 -- neutral within noise, so its cost was the lock and
the linear scans rather than time we can see.

Removed: the global cache, its lock, the entry table, the invalidation path, the
cache-only profiler fields and the synthetic probe. The proof classifier stays.

⚠️ I asked for this cache two days ago on the strength of a commandlet measurement that
re-visited the same region repeatedly. That access pattern is nothing like a moving
player, and I should have said so when specifying it.

VERIFIED BY ME: build 0 errors; export 0.563 / 0.565 / 0.566 s (35de59b was 0.545-0.563,
flat as expected); geometry SHA-256 b3e5f4c3..9b377 UNCHANGED; capability 20,830 /
10,909, connected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aheo2crrZmHuYtPpdY2Cb
This commit is contained in:
Fr0zkaandClaude Opus 5 committed 2026-09-12 06:49:20 +02:00
1 parent 35de59bac5
commit cf0319d480
12 files changed
+660 -514

No files matched your search

+1 -216
View File
@@ -22,7 +22,6 @@
#include "HAL/PlatformTime.h"
#include "HAL/IConsoleManager.h"
#include "Misc/CommandLine.h"
#include "Misc/ScopeLock.h"
#if WITH_EDITOR
#include "VoxelStrateComposer.h"
@@ -56,6 +55,7 @@ namespace
GVoxelForgeUseFusedEvaluator = CommandLineValue;
}
}
}
//=============================================================================
@@ -1532,169 +1532,6 @@ UVoxelGenerator::UVoxelGenerator()
{
}
void UVoxelGenerator::InvalidateTileVerdictCache() const
{
FScopeLock Lock(&TileVerdictCacheLock);
TileVerdictCache.Reset();
TileVerdictCacheClock = 0;
}
bool UVoxelGenerator::FindTileVerdict(
const FIntVector& OriginVoxels, int32 Step, int32 CellsPerAxis,
int32 ManagerWorldSeed, uint32 LayoutVersion, uint32 DiffVersion,
uint64 ParamsFingerprint, uint8 PassageSupportFloorWrites,
EVoxelTileClass& OutVerdict, bool& bOutRegionHit) const
{
bOutRegionHit = false;
FScopeLock Lock(&TileVerdictCacheLock);
++TileVerdictCacheClock;
const int64 RequestMaxX = static_cast<int64>(OriginVoxels.X)
+ static_cast<int64>(CellsPerAxis) * Step;
const int64 RequestMaxY = static_cast<int64>(OriginVoxels.Y)
+ static_cast<int64>(CellsPerAxis) * Step;
const int64 RequestMaxZ = static_cast<int64>(OriginVoxels.Z)
+ static_cast<int64>(CellsPerAxis) * Step;
int32 BestIndex = INDEX_NONE;
bool bBestExact = false;
for (int32 Index = 0; Index < TileVerdictCache.Num(); ++Index)
{
FTileVerdictCacheEntry& Entry = TileVerdictCache[Index];
if (Entry.GeneratorSeed != Seed
|| Entry.ManagerWorldSeed != ManagerWorldSeed
|| Entry.OriginSpineRadius != OriginSpineRadius
|| Entry.WorldRadiusVoxels != WorldRadiusVoxels
|| Entry.EdgeSealThickness != EdgeSealThickness
|| Entry.ManagerLifetimeId != (StrateManager ? StrateManager->GetCacheLifetimeId() : 0)
|| Entry.LayoutVersion != LayoutVersion
|| Entry.DiffVersion != DiffVersion
|| Entry.ParamsFingerprint != ParamsFingerprint
|| Entry.PassageSupportFloorWrites != PassageSupportFloorWrites
|| Entry.Step != Step
|| Entry.CellsPerAxis < CellsPerAxis)
{
continue;
}
const int64 EntryMaxX = static_cast<int64>(Entry.Origin.X)
+ static_cast<int64>(Entry.CellsPerAxis) * Step;
const int64 EntryMaxY = static_cast<int64>(Entry.Origin.Y)
+ static_cast<int64>(Entry.CellsPerAxis) * Step;
const int64 EntryMaxZ = static_cast<int64>(Entry.Origin.Z)
+ static_cast<int64>(Entry.CellsPerAxis) * Step;
const int64 DeltaX = static_cast<int64>(OriginVoxels.X) - Entry.Origin.X;
const int64 DeltaY = static_cast<int64>(OriginVoxels.Y) - Entry.Origin.Y;
const int64 DeltaZ = static_cast<int64>(OriginVoxels.Z) - Entry.Origin.Z;
if (DeltaX < 0 || DeltaY < 0 || DeltaZ < 0
|| (DeltaX % Step) != 0 || (DeltaY % Step) != 0 || (DeltaZ % Step) != 0
|| RequestMaxX > EntryMaxX || RequestMaxY > EntryMaxY || RequestMaxZ > EntryMaxZ)
{
continue;
}
const bool bExact = Entry.Origin == OriginVoxels
&& Entry.CellsPerAxis == CellsPerAxis;
if (BestIndex == INDEX_NONE || (bExact && !bBestExact)
|| (bExact == bBestExact
&& Entry.CellsPerAxis < TileVerdictCache[BestIndex].CellsPerAxis))
{
BestIndex = Index;
bBestExact = bExact;
}
}
if (BestIndex == INDEX_NONE)
{
return false;
}
FTileVerdictCacheEntry& Entry = TileVerdictCache[BestIndex];
Entry.LastUse = TileVerdictCacheClock;
OutVerdict = Entry.Verdict;
bOutRegionHit = !(Entry.Origin == OriginVoxels
&& Entry.CellsPerAxis == CellsPerAxis);
return OutVerdict != EVoxelTileClass::Mixed;
}
void UVoxelGenerator::StoreTileVerdict(
const FIntVector& OriginVoxels, int32 Step, int32 CellsPerAxis,
int32 ManagerWorldSeed, uint32 LayoutVersion, uint32 DiffVersion,
uint64 ParamsFingerprint, uint8 PassageSupportFloorWrites,
EVoxelTileClass Verdict) const
{
if (Verdict == EVoxelTileClass::Mixed)
{
return;
}
FScopeLock Lock(&TileVerdictCacheLock);
++TileVerdictCacheClock;
int32 SlotIndex = INDEX_NONE;
int32 VictimIndex = INDEX_NONE;
uint32 OldestUse = MAX_uint32;
for (int32 Index = 0; Index < TileVerdictCache.Num(); ++Index)
{
FTileVerdictCacheEntry& Entry = TileVerdictCache[Index];
if (Entry.GeneratorSeed == Seed
&& Entry.ManagerWorldSeed == ManagerWorldSeed
&& Entry.OriginSpineRadius == OriginSpineRadius
&& Entry.WorldRadiusVoxels == WorldRadiusVoxels
&& Entry.EdgeSealThickness == EdgeSealThickness
&& Entry.ManagerLifetimeId == (StrateManager ? StrateManager->GetCacheLifetimeId() : 0)
&& Entry.LayoutVersion == LayoutVersion
&& Entry.DiffVersion == DiffVersion
&& Entry.ParamsFingerprint == ParamsFingerprint
&& Entry.PassageSupportFloorWrites == PassageSupportFloorWrites
&& Entry.Origin == OriginVoxels
&& Entry.Step == Step
&& Entry.CellsPerAxis == CellsPerAxis)
{
SlotIndex = Index;
break;
}
if (Entry.LastUse < OldestUse)
{
OldestUse = Entry.LastUse;
VictimIndex = Index;
}
}
if (SlotIndex == INDEX_NONE)
{
if (TileVerdictCache.Num() < TileVerdictCacheCapacity)
{
SlotIndex = TileVerdictCache.AddDefaulted();
}
else if (VictimIndex != INDEX_NONE)
{
SlotIndex = VictimIndex;
}
else
{
return;
}
}
FTileVerdictCacheEntry& Entry = TileVerdictCache[SlotIndex];
Entry.Origin = OriginVoxels;
Entry.Step = Step;
Entry.CellsPerAxis = CellsPerAxis;
Entry.GeneratorSeed = Seed;
Entry.ManagerWorldSeed = ManagerWorldSeed;
Entry.OriginSpineRadius = OriginSpineRadius;
Entry.WorldRadiusVoxels = WorldRadiusVoxels;
Entry.EdgeSealThickness = EdgeSealThickness;
Entry.ManagerLifetimeId = StrateManager ? StrateManager->GetCacheLifetimeId() : 0;
Entry.LayoutVersion = LayoutVersion;
Entry.DiffVersion = DiffVersion;
Entry.ParamsFingerprint = ParamsFingerprint;
Entry.PassageSupportFloorWrites = PassageSupportFloorWrites;
Entry.Verdict = Verdict;
Entry.LastUse = TileVerdictCacheClock;
}
void UVoxelGenerator::InitializeSettings(const UVoxelSettings* Settings)
{
// Les paramètres globaux sont copiés ici une seule fois : le chemin voxel ne doit pas
@@ -1703,7 +1540,6 @@ void UVoxelGenerator::InitializeSettings(const UVoxelSettings* Settings)
OriginSpineRadius = Settings ? Settings->GetEffectiveOriginSpineRadius() : 14.0f;
WorldRadiusVoxels = Settings ? Settings->GetEffectiveWorldRadiusVoxels() : 0.0f;
EdgeSealThickness = Settings ? Settings->EdgeSealThickness : 64.0f;
InvalidateTileVerdictCache();
}
void UVoxelGenerator::BeginDensityBlock(FIntVector OriginVoxels, int32 Step,
@@ -5115,48 +4951,6 @@ EVoxelTileClass UVoxelGenerator::ClassifyTile(const FIntVector& OriginVoxels, in
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TileClassifyCalls);
const uint64 ParamsFingerprint = StrateManager
? StrateManager->GetGenerationParamsFingerprint() : 0;
const bool bCacheable = ParamsFingerprint != 0;
const uint32 LayoutVersion = StrateManager ? StrateManager->GetLayoutVersion() : 0;
const uint32 DiffVersion = DiffLayer ? DiffLayer->GetModsVersion() : 0;
const int32 ManagerWorldSeed = StrateManager ? StrateManager->GetWorldSeed() : 0;
const uint8 PassageSupportFloorWrites = StrateManager
&& StrateManager->ArePassageSupportFloorWritesEnabledForDiagnostics() ? 1u : 0u;
EVoxelTileClass CachedVerdict = EVoxelTileClass::Mixed;
bool bRegionHit = false;
if (bCacheable
&& FindTileVerdict(
OriginVoxels, NormalizedStep, NormalizedCellsPerAxis,
ManagerWorldSeed, LayoutVersion, DiffVersion, ParamsFingerprint,
PassageSupportFloorWrites, CachedVerdict, bRegionHit))
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TileVerdictCacheHits);
if (bRegionHit)
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TileVerdictRegionHits);
}
if (CachedVerdict == EVoxelTileClass::AllSolid)
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TileClassifyAllSolid);
}
else if (CachedVerdict == EVoxelTileClass::AllAir)
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TileClassifyAllAir);
}
else
{
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TileClassifyMixed);
}
return CachedVerdict;
}
const EVoxelTileClass Verdict = ClassifyTileUncached(
OriginVoxels, NormalizedStep, NormalizedCellsPerAxis, OutStats);
if (Verdict == EVoxelTileClass::AllSolid)
@@ -5175,15 +4969,6 @@ EVoxelTileClass UVoxelGenerator::ClassifyTile(const FIntVector& OriginVoxels, in
VoxelDensityProfile::ECounter::TileClassifyMixed);
}
if (bCacheable && Verdict != EVoxelTileClass::Mixed)
{
StoreTileVerdict(
OriginVoxels, NormalizedStep, NormalizedCellsPerAxis,
ManagerWorldSeed, LayoutVersion, DiffVersion, ParamsFingerprint,
PassageSupportFloorWrites, Verdict);
VoxelDensityProfile::AddCounter(
VoxelDensityProfile::ECounter::TileVerdictCacheStores);
}
return Verdict;
}