research: idle workers at 30 m/s (L122, no production change)
98% of idle-with-holes windows wait on the expanded critical set; region compile runs 0.26 ms but its gate stays pending 18 ms p50. Broad early admission: near +15.4 pt but p99 13.4 ms (over the VR 11 ms frame); near-only: +9.9 pt but far holes +1.5 pt. Trace instrumentation kept as a patch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
5c519f5206
commit
bae1144ee4
6 files changed
+960
No files matched your search
@@ -0,0 +1,218 @@
|
||||
diff --git a/Source/VoxelForge/Private/VoxelWorld.cpp b/Source/VoxelForge/Private/VoxelWorld.cpp
|
||||
index 42ac6f5..5c436ee 100644
|
||||
--- a/Source/VoxelForge/Private/VoxelWorld.cpp
|
||||
+++ b/Source/VoxelForge/Private/VoxelWorld.cpp
|
||||
@@ -195,10 +195,13 @@ public:
|
||||
std::atomic<bool> bShuttingDown{false};
|
||||
std::atomic<uint64> NextEditSequence{1};
|
||||
std::atomic<uint64> RegionCompileStartCycles{0};
|
||||
+ std::atomic<uint64> RegionCompileWorkerStartCycles{0};
|
||||
std::atomic<uint64> RegionCompileEndCycles{0};
|
||||
std::atomic<int32> RegionCompileTileCount{0};
|
||||
std::atomic<int32> RegionCompileSerial{0};
|
||||
+ std::atomic<uint32> RegionCompileWorkerThreadId{0};
|
||||
std::atomic<double> RegionCompileWorkerSeconds{0.0};
|
||||
+ std::atomic<double> RegionCompileWallSeconds{0.0};
|
||||
int32 FullResolutionLodCount = 0;
|
||||
FString InitialFailureReason;
|
||||
};
|
||||
@@ -11381,20 +11384,25 @@ void AVoxelWorld::StartPendingCoreRegionCompile()
|
||||
1, std::memory_order_relaxed) + 1;
|
||||
State->RegionCompileStartCycles.store(ActiveCoreRegionCompileStartCycles,
|
||||
std::memory_order_release);
|
||||
+ State->RegionCompileWorkerStartCycles.store(0, std::memory_order_release);
|
||||
State->RegionCompileEndCycles.store(0, std::memory_order_release);
|
||||
State->RegionCompileTileCount.store(0, std::memory_order_release);
|
||||
+ State->RegionCompileWorkerThreadId.store(0, std::memory_order_release);
|
||||
State->RegionCompileWorkerSeconds.store(0.0, std::memory_order_release);
|
||||
+ State->RegionCompileWallSeconds.store(0.0, std::memory_order_release);
|
||||
if (VoxelForgeStartupTrace::IsActive())
|
||||
{
|
||||
VoxelForgeStartupTrace::RecordEvent(TEXT("core_region_compile_start"), FString::Printf(
|
||||
TEXT("\"compile_serial\":%d,\"request_serial\":%d,\"center\":[%d,%d,%d],"
|
||||
"\"missing_region_tiles\":%d,\"retained_tiles\":%d,\"concurrent_admission\":%d,"
|
||||
- "\"active_tile_tasks\":%d,\"active_task_guard\":%d"),
|
||||
+ "\"active_tile_tasks\":%d,\"active_generation_workers\":%d,"
|
||||
+ "\"active_task_guard\":%d,\"game_thread_id\":%u"),
|
||||
CompileSerial, CoreRegionCompileRequestSerial,
|
||||
CompileCenter.X, CompileCenter.Y, CompileCenter.Z,
|
||||
MissingTiles.Num(), RetainedTiles.Num(), bAllowConcurrentGeneration ? 1 : 0,
|
||||
ActiveTileTaskCount.load(std::memory_order_relaxed),
|
||||
- ActiveTaskCount.load(std::memory_order_relaxed)));
|
||||
+ ActiveGenerationWorkerCount.load(std::memory_order_relaxed),
|
||||
+ ActiveTaskCount.load(std::memory_order_relaxed), FPlatformTLS::GetCurrentThreadId()));
|
||||
}
|
||||
ActiveTaskCount.fetch_add(1, std::memory_order_relaxed);
|
||||
UE::Tasks::Launch(TEXT("VoxelForgeCoreTileRegion"),
|
||||
@@ -11407,6 +11415,11 @@ void AVoxelWorld::StartPendingCoreRegionCompile()
|
||||
~FTaskGuard() { Counter.fetch_sub(1, std::memory_order_release); }
|
||||
} Guard{ActiveTaskCount};
|
||||
|
||||
+ State->RegionCompileWorkerStartCycles.store(FPlatformTime::Cycles64(),
|
||||
+ std::memory_order_release);
|
||||
+ State->RegionCompileWorkerThreadId.store(FPlatformTLS::GetCurrentThreadId(),
|
||||
+ std::memory_order_release);
|
||||
+
|
||||
if (bShuttingDown.load(std::memory_order_acquire)
|
||||
|| State->bShuttingDown.load(std::memory_order_acquire))
|
||||
{
|
||||
@@ -11458,6 +11471,8 @@ void AVoxelWorld::StartPendingCoreRegionCompile()
|
||||
}
|
||||
State->RegionCompileWorkerSeconds.store(CompileStats.workerSeconds,
|
||||
std::memory_order_release);
|
||||
+ State->RegionCompileWallSeconds.store(CompileStats.wallSeconds,
|
||||
+ std::memory_order_release);
|
||||
State->bRegionCompileSucceeded.store(bCompiled, std::memory_order_release);
|
||||
if (!bCompiled)
|
||||
{
|
||||
@@ -12345,9 +12360,17 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
State->RegionCompileStartCycles.load(std::memory_order_acquire);
|
||||
const uint64 CompileEndCycles =
|
||||
State->RegionCompileEndCycles.load(std::memory_order_acquire);
|
||||
+ const uint64 CompileWorkerStartCycles =
|
||||
+ State->RegionCompileWorkerStartCycles.load(std::memory_order_acquire);
|
||||
const double CompileElapsedMilliseconds = CompileEndCycles >= CompileStartCycles
|
||||
? FPlatformTime::ToSeconds64(CompileEndCycles - CompileStartCycles) * 1000.0
|
||||
: 0.0;
|
||||
+ const double CompileQueueMilliseconds = CompileWorkerStartCycles >= CompileStartCycles
|
||||
+ ? FPlatformTime::ToSeconds64(CompileWorkerStartCycles - CompileStartCycles) * 1000.0
|
||||
+ : 0.0;
|
||||
+ const double CompileTaskMilliseconds = CompileEndCycles >= CompileWorkerStartCycles
|
||||
+ ? FPlatformTime::ToSeconds64(CompileEndCycles - CompileWorkerStartCycles) * 1000.0
|
||||
+ : 0.0;
|
||||
const double GateElapsedMilliseconds = CoreRegionPendingSinceSeconds > 0.0
|
||||
? FMath::Max(0.0, FPlatformTime::Seconds() - CoreRegionPendingSinceSeconds) * 1000.0
|
||||
: 0.0;
|
||||
@@ -12355,6 +12378,10 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
State->RegionCompileTileCount.load(std::memory_order_acquire);
|
||||
const double CompileWorkerSeconds =
|
||||
State->RegionCompileWorkerSeconds.load(std::memory_order_acquire);
|
||||
+ const double CompileCoreWallSeconds =
|
||||
+ State->RegionCompileWallSeconds.load(std::memory_order_acquire);
|
||||
+ const uint32 CompileWorkerThreadId =
|
||||
+ State->RegionCompileWorkerThreadId.load(std::memory_order_acquire);
|
||||
const int32 CompileSerial =
|
||||
State->RegionCompileSerial.load(std::memory_order_acquire);
|
||||
const uint64 IndependentSubmissions = CoreRegionIndependentSubmissions;
|
||||
@@ -12364,14 +12391,20 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
VoxelForgeStartupTrace::RecordEvent(TEXT("core_region_compile_complete"), FString::Printf(
|
||||
TEXT("\"compile_serial\":%d,\"request_serial\":%d,\"center\":[%d,%d,%d],"
|
||||
"\"success\":%d,\"compiled_tiles\":%d,\"compile_elapsed_ms\":%s,"
|
||||
- "\"compile_worker_s\":%s,\"pending_gate_elapsed_ms\":%s,"
|
||||
+ "\"compile_queue_ms\":%s,\"compile_task_ms\":%s,"
|
||||
+ "\"compile_core_wall_ms\":%s,\"compile_worker_s\":%s,"
|
||||
+ "\"compile_worker_thread_id\":%u,\"pending_gate_elapsed_ms\":%s,"
|
||||
"\"independent_submissions\":%llu,"
|
||||
"\"dependent_declines\":%llu,\"concurrent_admission\":%d"),
|
||||
CompileSerial, ActiveCoreRegionCompileRequestSerial,
|
||||
ActiveCoreRegionCompileCenter.X, ActiveCoreRegionCompileCenter.Y,
|
||||
ActiveCoreRegionCompileCenter.Z, bRegionCompileSucceeded ? 1 : 0,
|
||||
CompiledTileCount, *FString::SanitizeFloat(CompileElapsedMilliseconds),
|
||||
+ *FString::SanitizeFloat(CompileQueueMilliseconds),
|
||||
+ *FString::SanitizeFloat(CompileTaskMilliseconds),
|
||||
+ *FString::SanitizeFloat(CompileCoreWallSeconds * 1000.0),
|
||||
*FString::SanitizeFloat(CompileWorkerSeconds),
|
||||
+ CompileWorkerThreadId,
|
||||
*FString::SanitizeFloat(GateElapsedMilliseconds),
|
||||
static_cast<unsigned long long>(IndependentSubmissions),
|
||||
static_cast<unsigned long long>(DependentDeclines),
|
||||
@@ -12584,6 +12617,8 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
&& bWalkableRingReadyForReserve;
|
||||
int32 SchedulerSubmittedByLevel[9] = {};
|
||||
int32 SchedulerLoadAttemptsByLevel[9] = {};
|
||||
+ int32 SchedulerRegionCompileDeclinesByLevel[9] = {};
|
||||
+ int32 SchedulerFarParentDeclinesByLevel[9] = {};
|
||||
int32 SchedulerLevelCapReturns[9] = {};
|
||||
int32 SchedulerLevelCapBreaks[9] = {};
|
||||
int32 SchedulerCriticalFullCapBreaks = 0;
|
||||
@@ -12951,7 +12986,21 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
if(CoreState.IsValid()
|
||||
&&CoreState->bFarWorldRequired.load(std::memory_order_acquire)
|
||||
&&!CoreState->bFarWorldReady.load(std::memory_order_acquire))
|
||||
+ {
|
||||
+ if (bTraceStreamingScheduler && Tile.Level >= 0 && Tile.Level < 9)
|
||||
+ {
|
||||
+ ++SchedulerFarParentDeclinesByLevel[Tile.Level];
|
||||
+ }
|
||||
return;
|
||||
+ }
|
||||
+ }
|
||||
+ if (bTraceStreamingScheduler && bUseVoxelForgeCore && bCoreRegionCompilePending
|
||||
+ && GVoxelForgeCoreRegionConcurrentAdmission != 0
|
||||
+ && (PendingCoreRegionTileSet.Contains(Tile)
|
||||
+ || CoreRegionCompileTilesInFlight.Contains(Tile))
|
||||
+ && Tile.Level >= 0 && Tile.Level < 9)
|
||||
+ {
|
||||
+ ++SchedulerRegionCompileDeclinesByLevel[Tile.Level];
|
||||
}
|
||||
if (Tile.Level >= 0 && Tile.Level < 9)
|
||||
{
|
||||
@@ -13661,10 +13710,37 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
const double BusySeconds = FPlatformTime::ToSeconds64(WorkerCyclesDelta);
|
||||
const double SchedulerUpdateMilliseconds = (SchedulerTraceNow
|
||||
- StreamingUpdateStartSeconds) * 1000.0;
|
||||
+ int32 CriticalMissingTiles = 0;
|
||||
+ for (const FVoxelTileKey& Tile : CriticalDesiredTiles)
|
||||
+ {
|
||||
+ if (!LoadedTiles.Contains(Tile) && !CollisionNotRequiredTiles.Contains(Tile))
|
||||
+ {
|
||||
+ ++CriticalMissingTiles;
|
||||
+ }
|
||||
+ }
|
||||
+ int32 CollisionGateMissingTiles = 0;
|
||||
+ for (const FVoxelTileKey& Tile : CollisionGateDesiredTiles)
|
||||
+ {
|
||||
+ if (!LoadedTiles.Contains(Tile) && !CollisionNotRequiredTiles.Contains(Tile))
|
||||
+ {
|
||||
+ ++CollisionGateMissingTiles;
|
||||
+ }
|
||||
+ }
|
||||
+ const FIntVector DesiredCenterLag = DesiredEpochCenterChunk - CenterChunk;
|
||||
+ const TSharedPtr<FVoxelForgeCoreRuntimeState, ESPMode::ThreadSafe> TraceCoreState =
|
||||
+ VoxelForgeCoreState;
|
||||
+ const bool bFarWorldRequiredForTrace = TraceCoreState.IsValid()
|
||||
+ && TraceCoreState->bFarWorldRequired.load(std::memory_order_relaxed);
|
||||
+ const bool bFarWorldReadyForTrace = TraceCoreState.IsValid()
|
||||
+ && TraceCoreState->bFarWorldReady.load(std::memory_order_relaxed);
|
||||
VoxelForgeStartupTrace::RecordEvent(TEXT("scheduler_admission"), FString::Printf(
|
||||
TEXT("\"frame\":%llu,\"center\":[%d,%d,%d],\"desired_rebuilt\":%d,"
|
||||
"\"submission_loop_ran\":%d,\"all_chunks_loaded\":%d,"
|
||||
"\"walkable_ready\":%d,\"moving\":%d,"
|
||||
+ "\"pawn_collision_gate_engaged\":%d,\"critical_tiles_ready\":%d,"
|
||||
+ "\"critical_missing\":%d,\"collision_gate_missing\":%d,"
|
||||
+ "\"desired_center_lag\":[%d,%d,%d],\"desired_center_current\":%d,"
|
||||
+ "\"far_world_required\":%d,\"far_world_ready\":%d,"
|
||||
"\"core_region_compile_pending\":%d,\"core_ready\":%d,\"coarse_first\":%d,"
|
||||
"\"dynamic_near_reserve\":%d,\"legacy_pending_result_cap\":%d,"
|
||||
"\"core_region_concurrent_admission\":%d,"
|
||||
@@ -13685,6 +13761,8 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
"\"level_candidate_scan_ms\":%s,\"passage_score_ms\":%s,"
|
||||
"\"level_sort_ms\":%s,\"level_admit_ms\":%s,"
|
||||
"\"desired_missing_by_lod\":%s,\"loaded_by_lod\":%s,\"pending_by_lod\":%s,"
|
||||
+ "\"region_compile_declines_by_lod\":%s,"
|
||||
+ "\"far_parent_declines_by_lod\":%s,"
|
||||
"\"submitted_by_lod\":%s,\"load_attempts_by_lod\":%s,"
|
||||
"\"admission_cap_by_lod\":%s,\"declined_rule_by_lod\":%s,"
|
||||
"\"level_cap_returns_by_lod\":%s,\"level_cap_breaks_by_lod\":%s,"
|
||||
@@ -13695,6 +13773,11 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
static_cast<unsigned long long>(GFrameCounter), CenterChunk.X, CenterChunk.Y, CenterChunk.Z,
|
||||
bDesiredRebuiltThisUpdate ? 1 : 0, bSubmissionLoopRan ? 1 : 0, bAllChunksLoaded ? 1 : 0,
|
||||
bWalkableRingReadyForReserve ? 1 : 0, bPawnMoving ? 1 : 0,
|
||||
+ bPawnCollisionGateEngaged ? 1 : 0, CriticalMissingTiles == 0 ? 1 : 0,
|
||||
+ CriticalMissingTiles, CollisionGateMissingTiles,
|
||||
+ DesiredCenterLag.X, DesiredCenterLag.Y, DesiredCenterLag.Z,
|
||||
+ DesiredCenterLag == FIntVector::ZeroValue ? 1 : 0,
|
||||
+ bFarWorldRequiredForTrace ? 1 : 0, bFarWorldReadyForTrace ? 1 : 0,
|
||||
bCoreRegionCompilePending ? 1 : 0, IsVoxelForgeCoreReady() ? 1 : 0,
|
||||
GVoxelForgeStreamingCoarseFirst, GVoxelForgeStreamingDynamicNearReserve,
|
||||
GVoxelForgeStreamingLegacyPendingResultCap,
|
||||
@@ -13721,7 +13804,8 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
|
||||
*FString::SanitizeFloat(LevelSortMilliseconds),
|
||||
*FString::SanitizeFloat(LevelAdmissionMilliseconds),
|
||||
*IntArrayJson(DesiredMissingByLevel), *IntArrayJson(LoadedByLevel),
|
||||
- *IntArrayJson(PendingByLevel), *IntArrayJson(SchedulerSubmittedByLevel),
|
||||
+ *IntArrayJson(PendingByLevel), *IntArrayJson(SchedulerRegionCompileDeclinesByLevel),
|
||||
+ *IntArrayJson(SchedulerFarParentDeclinesByLevel), *IntArrayJson(SchedulerSubmittedByLevel),
|
||||
*IntArrayJson(SchedulerLoadAttemptsByLevel), *IntArrayJson(AdmissionCapByLevel),
|
||||
*IntArrayJson(DeclinedRuleByLevel), *IntArrayJson(SchedulerLevelCapReturns),
|
||||
*IntArrayJson(SchedulerLevelCapBreaks), FullCapDeclinedTiles, ReserveDeclinedTiles,
|
||||
Reference in new issue
Block a user