- Per-frame passage-overlap scoring over outstanding tiles (added in L85) measured 121 ms for 407 LOD2 candidates; removed (deterministic desired/travel order kept). - Visibility reconciliation read-locked the Core world per candidate while the far-world build held the writer lock (162 ms scan, 123 ms lock wait); the immutable render distance is cached. Visibility now <= 0.17 ms. - Ready player-support collision tiles stay in the collision-desired set: fixes the L95 SW outlier (LOD0 (3,0,-47/-48/-50) re-admitted); 6 SW runs without re-admission. - AVoxelWorld::Tick during the arrival burst: FI p99 3.7-4.3 ms (max 6.0), SW p99 8.2-8.9 ms (max 11.2). FI still shows rare 40-60 ms world ticks outside our actor scope (engine tick group). - Near-set times kept: FI 2.06-2.12 s, SW median 1.30 s after first admission. World unchanged. Fast tier PASS; Linux UE host builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
118 lines
4.2 KiB
C++
118 lines
4.2 KiB
C++
// Bounded, opt-in startup trace for the complete streaming path.
|
|
// The trace is deliberately independent of the shared Unreal log: callers provide an
|
|
// absolute output path and every record is one JSON object per line.
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
namespace VoxelForgeStartupTrace
|
|
{
|
|
struct VOXELFORGE_API FTileSample
|
|
{
|
|
int32 TileX = 0;
|
|
int32 TileY = 0;
|
|
int32 TileZ = 0;
|
|
int32 Level = -1;
|
|
int32 WorkPriority = 0;
|
|
int32 Verdict = -1; // Mixed=0, AllSolid=1, AllAir=2, -1=not classified (early path)
|
|
uint64 RequestOrdinal = 0;
|
|
uint64 GenerationOrdinal = 0;
|
|
uint64 RequestStartCycles = 0;
|
|
uint64 WorkerTaskStartCycles = 0;
|
|
uint64 WorkerTaskEndCycles = 0;
|
|
uint32 WorkerThreadId = 0;
|
|
bool bResidentAtRequest = false;
|
|
bool bSealedSolidProof = false;
|
|
bool bEmpty = true;
|
|
int32 Vertices = 0;
|
|
int32 Triangles = 0;
|
|
uint64 GeometryBytes = 0;
|
|
// This is worker-result -> game-thread mesh submission. Collision readiness is a later
|
|
// per-tile RMC completion event recorded separately as collision_ready.
|
|
double RequestToApplySeconds = 0.0;
|
|
double QueueWaitSeconds = 0.0;
|
|
double WorkerQueueSeconds = 0.0;
|
|
double ResultQueueSeconds = 0.0;
|
|
double WorkerTaskSeconds = 0.0;
|
|
double GenerationSeconds = 0.0;
|
|
double CoreGenerateSeconds = 0.0;
|
|
double MeshCopySeconds = 0.0;
|
|
double StreamBuildSeconds = 0.0;
|
|
double ClassifySeconds = 0.0;
|
|
double MeshSeconds = 0.0;
|
|
double StreamSeconds = 0.0;
|
|
double ApplySeconds = 0.0;
|
|
};
|
|
|
|
struct VOXELFORGE_API FApplyFrameSample
|
|
{
|
|
uint64 Frame = 0;
|
|
double FrameSeconds = 0.0;
|
|
double SpeedCmPerSecond = 0.0;
|
|
double ApplySeconds = 0.0;
|
|
double DrainSeconds = 0.0;
|
|
int32 ActiveTasks = 0;
|
|
int32 RunningWorkerTasks = 0;
|
|
int32 TaskCap = 0;
|
|
int32 PendingTiles = 0;
|
|
int32 PendingResultsEstimate = 0;
|
|
int32 ResultsDrained = 0;
|
|
int32 ApplyResultsByLevelTotal = 0;
|
|
int32 MeshesApplied = 0;
|
|
int32 MaxApplies = 0;
|
|
double ApplyBudgetMilliseconds = 0.0;
|
|
bool bCountLimitReached = false;
|
|
bool bTimeLimitReached = false;
|
|
TStaticArray<int32, 9> PendingByLevel{};
|
|
TStaticArray<int32, 9> ApplyResultsByLevel{};
|
|
TStaticArray<int32, 9> MeshesAppliedByLevel{};
|
|
TStaticArray<double, 9> ApplySecondsByLevel{};
|
|
};
|
|
|
|
struct VOXELFORGE_API FWriteMetrics
|
|
{
|
|
double JsonWriteMilliseconds = 0.0;
|
|
double ArchiveSerializeMilliseconds = 0.0;
|
|
};
|
|
|
|
/** Starts when -voxel.StartupTraceFile=<absolute path> is present. */
|
|
VOXELFORGE_API void BeginFromCommandLine();
|
|
|
|
VOXELFORGE_API bool IsActive();
|
|
|
|
/** Returns and resets startup-trace writes performed by the current game-thread frame. */
|
|
VOXELFORGE_API FWriteMetrics ConsumeCurrentThreadWriteMetrics();
|
|
|
|
/** FieldsJson is the contents after the type/timestamp object prefix, without braces. */
|
|
VOXELFORGE_API void RecordEvent(const TCHAR* Type, const FString& FieldsJson = FString());
|
|
|
|
VOXELFORGE_API void RecordRequest(const FTileSample& Sample, uint32 Epoch);
|
|
|
|
VOXELFORGE_API void StageBegin(const TCHAR* Name);
|
|
VOXELFORGE_API void StageEnd(const TCHAR* Name);
|
|
|
|
VOXELFORGE_API void RecordTile(const FTileSample& Sample);
|
|
|
|
/** One game-thread result-drain sample, including worker occupancy and per-LOD applies. */
|
|
/** Echantillon de vidage des resultats, avec occupation des travailleurs et applications par LOD. */
|
|
VOXELFORGE_API void RecordApplyFrame(const FApplyFrameSample& Sample);
|
|
|
|
/** Writes the final bounded summary and closes the file. Safe to call more than once. */
|
|
VOXELFORGE_API void Finish(const TCHAR* Reason);
|
|
|
|
/** RAII helper for stages which have early-return failure paths. */
|
|
class VOXELFORGE_API FStageScope
|
|
{
|
|
public:
|
|
explicit FStageScope(const TCHAR* InName);
|
|
~FStageScope();
|
|
|
|
FStageScope(const FStageScope&) = delete;
|
|
FStageScope& operator=(const FStageScope&) = delete;
|
|
|
|
private:
|
|
FString Name;
|
|
bool bActive = false;
|
|
};
|
|
}
|