diag: corrected passage-off ceiling + cold worker/tile timelines (L87); passages ARE the gate
L86's switch left ApplyResolvedStratePassageCarves running (near-tile service unchanged at ~21 worker-s), so its "no change" ceiling was wrong. Corrected (bands + carves off): FI LOD0-2 2.34 -> 0.66 s, whole 3.47 -> 1.49 s @W12; TN 2.27 -> 0.74 / 3.28 -> 1.52 s. Near-tile service 15.6-22.5 -> 2.6-3.8 worker-s. Critical chain: shape/base compile -> LOD0-1 -> far-parent build (107-153 ms, pipeline thread) -> LOD2. Workers 81-85% busy in the direct window. No production scheduling change; hashes equal L85. Fast tier PASS. 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
4f5f6667ae
commit
0fe7f371f7
8 files changed
+797
-20
No files matched your search
@@ -49,6 +49,7 @@ namespace
|
||||
bool ProfileLodWork=false;
|
||||
bool ProfilePassageComposer=false;
|
||||
bool InstrumentTileDrain=false;
|
||||
bool ColdWorkerTimeline=false;
|
||||
bool Linux77Profile=false;
|
||||
bool ExactMidpointDensityMemo=false;
|
||||
bool ActiveLaneBatching=false;
|
||||
@@ -1450,6 +1451,7 @@ namespace
|
||||
" --audit-uniform-block-proofs (fill and check every interval-certified block)\n"
|
||||
" --profile-lod-work (report per-LOD density sample counts)\n"
|
||||
" --instrument-tile-drain (opt-in CpuTileTimeline and per-tile stages/counters)\n"
|
||||
" --cold-worker-timeline (record requested/admitted/published tiles and worker idle spans)\n"
|
||||
" --linux77-profile (Linux-only SIGPROF stack and route census)\n"
|
||||
" --profile-passage-composer (emit per-tile passage work counters)\n"
|
||||
" --exact-midpoint-density-memo (exact-input midpoint query memo A/B)\n"
|
||||
@@ -1509,6 +1511,7 @@ namespace
|
||||
else if(arg=="--audit-uniform-block-proofs")options.AuditUniformBlockProofs=true;
|
||||
else if(arg=="--profile-lod-work")options.ProfileLodWork=true;
|
||||
else if(arg=="--instrument-tile-drain")options.InstrumentTileDrain=true;
|
||||
else if(arg=="--cold-worker-timeline")options.ColdWorkerTimeline=true;
|
||||
else if(arg=="--linux77-profile")
|
||||
{options.Linux77Profile=true;options.ProfileLodWork=true;}
|
||||
else if(arg=="--profile-passage-composer")
|
||||
@@ -2273,5 +2276,5 @@ int main(int argc,char** argv)
|
||||
options.StreamHashAllowUniformSkips,options.Linux77Profile,
|
||||
options.StreamingSchedulerPolicy,options.MovingCameraTrace,
|
||||
options.MovingCameraSpeedMetersPerSecond,options.MovingCameraDurationSeconds,
|
||||
options.MovingCameraDwellSeconds);
|
||||
options.MovingCameraDwellSeconds,options.ColdWorkerTimeline);
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
@@ -1883,9 +1884,23 @@ namespace StandaloneStreamBenchmark
|
||||
bool bProfilePassageComposer=false,bool bAllowUniformSkipsWhenHashing=false,
|
||||
bool bLinux77Profile=false,int32 SchedulerPolicy=-1,
|
||||
bool bMovingCameraTrace=false,double MovingCameraSpeedMetersPerSecond=0.0,
|
||||
double MovingCameraDurationSeconds=12.0,double MovingCameraDwellSeconds=5.0)
|
||||
double MovingCameraDurationSeconds=12.0,double MovingCameraDwellSeconds=5.0,
|
||||
bool bColdWorkerTimeline=false)
|
||||
{
|
||||
using Clock=std::chrono::steady_clock;
|
||||
const std::clock_t ColdCpuOrigin=std::clock();
|
||||
const bool bColdTimeline=bColdWorkerTimeline||bInstrumentTileDrain;
|
||||
const auto EmitColdTimeline=[&](const char* Event,const char* Edge,Clock::time_point At)
|
||||
{
|
||||
if(!bColdTimeline)return;
|
||||
const double CpuMilliseconds=1000.0*static_cast<double>(
|
||||
std::clock()-ColdCpuOrigin)/CLOCKS_PER_SEC;
|
||||
std::printf("[ColdTimeline] event=%s edge=%s at_ms=%.3f cpu_ms=%.3f\n",Event,Edge,
|
||||
std::chrono::duration<double,std::milli>(At-ColdStart).count(),CpuMilliseconds);
|
||||
std::fflush(stdout);
|
||||
};
|
||||
const auto MarkColdTimeline=[&](const char* Event,const char* Edge)
|
||||
{EmitColdTimeline(Event,Edge,Clock::now());};
|
||||
FStandaloneOwnerWorld& World=*OwnerWorld;
|
||||
const VoxelForgeCore::WorldAssemblyManifest* Assembly=CoreSnapshot.worldAssembly();
|
||||
std::array<double,9> ClosestDisplayDistances{};
|
||||
@@ -1913,6 +1928,8 @@ namespace StandaloneStreamBenchmark
|
||||
if(MaxLevel>=0)
|
||||
Desired.Tiles.erase(std::remove_if(Desired.Tiles.begin(),Desired.Tiles.end(),
|
||||
[&](const FVoxelTileKey& Tile){return Tile.Level>MaxLevel;}),Desired.Tiles.end());
|
||||
const Clock::time_point DesiredRequestAt=Clock::now();
|
||||
EmitColdTimeline("desired_tile_set","requested",DesiredRequestAt);
|
||||
const bool bHasCameraStep=std::abs(CameraStepVoxels.X)+std::abs(CameraStepVoxels.Y)
|
||||
+std::abs(CameraStepVoxels.Z)>1.0e-6f;
|
||||
FStandaloneDesiredTileSet MovedDesired;
|
||||
@@ -2049,9 +2066,15 @@ namespace StandaloneStreamBenchmark
|
||||
ShapeRequest.detail=DetailVariant;ShapeRequest.includeFarWorld=bIncludeFarWorld&&!bDeferFarWorld;
|
||||
ShapeRequest.roundTunnels=bRoundTunnels;
|
||||
ShapeRequest.enhancedTunnelWalls=bEnhancedTunnelWalls;
|
||||
ShapeRequest.validatePassageRoutes=!bCaptureSkipWalkability;
|
||||
const char* L86DisablePassages=std::getenv(
|
||||
"VOXELFORGE_L86_DISABLE_PASSAGE_COMPOSITION");
|
||||
const bool bL86DisablePassages=L86DisablePassages
|
||||
&&L86DisablePassages[0]=='1'&&L86DisablePassages[1]=='\0';
|
||||
ShapeRequest.validatePassageRoutes=!bCaptureSkipWalkability&&!bL86DisablePassages;
|
||||
if(bCaptureSkipWalkability)
|
||||
std::printf("[CaptureWalkabilityGate] validation=deferred geometry_input=unchanged mode=mesh-export\n");
|
||||
if(bL86DisablePassages)
|
||||
std::printf("[L86PassageCeiling] validation=skipped geometry=passage_composition_disabled diagnostic_only=true\n");
|
||||
FStandaloneStreamingGenerator Streamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel,
|
||||
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape,bProfileColumnOverlap,
|
||||
FarHorizonLOD8InteriorStepVoxels,bUseSharedColumnCache,
|
||||
@@ -2067,9 +2090,14 @@ namespace StandaloneStreamBenchmark
|
||||
Streamer.SetProofBlockCells(ProofBlockCells);
|
||||
if(bScreenSpaceGate||bReportLodWorkProfile||bInstrumentTileDrain||bLinux77Profile)
|
||||
Streamer.SetMesherStageProfilingEnabled(true);
|
||||
if(bInstrumentTileDrain)
|
||||
if(bColdTimeline)
|
||||
{
|
||||
Streamer.EnableColdTimelineTrace(ColdStart,nullptr);
|
||||
Streamer.RecordColdTimelineRequests(Desired.Tiles,DesiredRequestAt);
|
||||
EmitColdTimeline("desired_tile_set","request_recorded",Clock::now());
|
||||
}
|
||||
if(bInstrumentTileDrain)
|
||||
{
|
||||
std::printf("[CpuTileInstrumentation] enabled=true labeled=true flush=after_run proof_block_cells=%d active_lane_batching=%s midpoint_density_memo=%s parallel_sign_edge_repair=%s\n",
|
||||
ProofBlockCells,bActiveLaneBatching?"on":"off",
|
||||
bExactMidpointDensityMemo?"on":"off",
|
||||
@@ -2077,13 +2105,17 @@ namespace StandaloneStreamBenchmark
|
||||
}
|
||||
if(bLinux77Profile)VoxelForgeCore::Linux77Profiler::Start(1000);
|
||||
const auto StreamStart=Clock::now();
|
||||
MarkColdTimeline("initial_shape_free_admission","begin");
|
||||
const FStandaloneStreamingUpdate EarlyUpdate=Streamer.StartWithDesired(ShapeFreeDesired);
|
||||
MarkColdTimeline("initial_shape_free_admission","end");
|
||||
if(EarlyUpdate.DesiredTiles!=static_cast<int32>(ShapeFreeDesired.Tiles.size()))
|
||||
{
|
||||
Streamer.Stop();
|
||||
std::fprintf(stderr,"[StreamPipeline] expected %zu shape-free tiles but queued %d.\n",
|
||||
ShapeFreeDesired.Tiles.size(),EarlyUpdate.DesiredTiles);return 7;
|
||||
}
|
||||
MarkColdTimeline("shape_compile","begin");
|
||||
MarkColdTimeline("base_compile","begin");
|
||||
const auto ShapeBuildStart=Clock::now();
|
||||
auto ShapeBuildFuture=std::async(std::launch::async,
|
||||
[&Shape,&Scheduler,ShapeRequest,DiagnosticSlowShapeCompileMs]() mutable
|
||||
@@ -2095,6 +2127,8 @@ namespace StandaloneStreamBenchmark
|
||||
return std::pair<bool,std::string>{bCompiled,std::move(Error)};
|
||||
});
|
||||
const auto [bShapeCompiled,BuildError]=ShapeBuildFuture.get();
|
||||
MarkColdTimeline("base_compile","end");
|
||||
MarkColdTimeline("shape_compile","end");
|
||||
if(!bShapeCompiled)
|
||||
{
|
||||
Streamer.Stop();
|
||||
@@ -4994,8 +5028,10 @@ namespace StandaloneStreamBenchmark
|
||||
const int32 EarlyDesiredCount=static_cast<int32>(EarlyDesired.Tiles.size());
|
||||
const int32 InitialDesiredCount=bDeferFarWorld?EarlyDesiredCount:
|
||||
static_cast<int32>(Desired.Tiles.size());
|
||||
MarkColdTimeline("lod0_1_admission","begin");
|
||||
FStandaloneStreamingUpdate Update=Streamer.UpdateDesiredWithSet(
|
||||
bDeferFarWorld?EarlyDesired:Desired,{},0);
|
||||
MarkColdTimeline("lod0_1_admission","end");
|
||||
if(Update.DesiredTiles!=InitialDesiredCount)
|
||||
{
|
||||
Streamer.Stop();
|
||||
@@ -5003,7 +5039,9 @@ namespace StandaloneStreamBenchmark
|
||||
InitialDesiredCount,Update.DesiredTiles);return 7;
|
||||
}
|
||||
double DeferredFarShapeSeconds=0.0;
|
||||
Clock::time_point EarlyTilesDoneAt{};
|
||||
bool bDeferredFarTilesQueued=false;
|
||||
bool bLOD01DoneMarked=false;
|
||||
if(bDeferFarWorld)
|
||||
std::printf("[ShapeSchedule] defer_far_parents=1 early_tiles=%d late_tiles=%zu start=after_base_shape_compile\n",
|
||||
EarlyDesiredCount,Desired.Tiles.size()-EarlyDesired.Tiles.size());
|
||||
@@ -5242,9 +5280,10 @@ namespace StandaloneStreamBenchmark
|
||||
*VoxelForgeCore::Linux77Profiler::RouteCount*2>,9> L77DispatchByLOD{};
|
||||
std::array<std::uint64_t,9> L77GridInteriorByLOD{},L77GridHaloByLOD{};
|
||||
std::array<double,9> L77LODReadySeconds{};
|
||||
std::array<double,9> LODReadySeconds{};
|
||||
std::array<double,9> LODReadySeconds{},LODPublishedReadySeconds{},LODPipelineReadySeconds{};
|
||||
std::array<std::uint64_t,9> SkirtTrianglesByLOD{};
|
||||
std::array<std::uint64_t,9> TileCountByLOD{};
|
||||
bool bLOD2DoneMarked=false;
|
||||
std::array<std::uint64_t,9> ClassifiedAirTilesByLOD{},ClassifiedSolidTilesByLOD{};
|
||||
std::array<std::uint64_t,9> ClassifiedMixedTilesByLOD{},UnclassifiedTilesByLOD{};
|
||||
std::array<std::uint64_t,9> MeshingSkippedTilesByLOD{},DensityGridTilesByLOD{};
|
||||
@@ -5311,9 +5350,19 @@ namespace StandaloneStreamBenchmark
|
||||
const std::size_t LOD=static_cast<std::size_t>(Tile.Key.Level);
|
||||
const auto& TileDiagnostics=Tile.CoreDiagnostics;
|
||||
++TileCountByLOD[LOD];
|
||||
if(TileCountByLOD[LOD]==ExpectedTilesByLOD[LOD])
|
||||
LODReadySeconds[LOD]=std::chrono::duration<double>(
|
||||
Tile.CompletedAt-ColdStart).count();
|
||||
LODReadySeconds[LOD]=std::max(LODReadySeconds[LOD],
|
||||
std::chrono::duration<double>(Tile.CompletedAt-ColdStart).count());
|
||||
LODPublishedReadySeconds[LOD]=std::max(LODPublishedReadySeconds[LOD],
|
||||
std::chrono::duration<double>(Tile.PublishedAt-ColdStart).count());
|
||||
LODPipelineReadySeconds[LOD]=std::max(LODPipelineReadySeconds[LOD],
|
||||
std::chrono::duration<double>(Tile.DrainedAt-ColdStart).count());
|
||||
if(LOD==2&&!bLOD2DoneMarked
|
||||
&&TileCountByLOD[LOD]==ExpectedTilesByLOD[LOD])
|
||||
{
|
||||
MarkColdTimeline("lod2_done","pipeline_drain");
|
||||
MarkColdTimeline("lod0_2_done","pipeline_drain");
|
||||
bLOD2DoneMarked=true;
|
||||
}
|
||||
if(bLinux77Profile)
|
||||
{
|
||||
const auto& D=TileDiagnostics;
|
||||
@@ -5518,17 +5567,32 @@ namespace StandaloneStreamBenchmark
|
||||
FullDetailFinished,FullDetailExpected);
|
||||
bFullDetailReported=true;
|
||||
}
|
||||
if(!bLOD01DoneMarked&&Finished==EarlyDesiredCount)
|
||||
{
|
||||
EarlyTilesDoneAt=Clock::now();
|
||||
EmitColdTimeline("lod0_1_done","publish_drained",EarlyTilesDoneAt);
|
||||
bLOD01DoneMarked=true;
|
||||
}
|
||||
if(bDeferFarWorld&&!bDeferredFarTilesQueued&&Finished==EarlyDesiredCount
|
||||
&&Desired.Tiles.size()>EarlyDesired.Tiles.size())
|
||||
{
|
||||
MarkColdTimeline("far_parent_build","begin");
|
||||
const auto FarBuildStart=Clock::now();
|
||||
Shape.buildFarWorld();
|
||||
if(!Shape.buildFarWorld())
|
||||
{
|
||||
Streamer.Stop();
|
||||
std::fprintf(stderr,"[StreamPipeline] deferred far-world build failed.\n");
|
||||
return 2;
|
||||
}
|
||||
DeferredFarShapeSeconds=std::chrono::duration<double>(
|
||||
Clock::now()-FarBuildStart).count();
|
||||
MarkColdTimeline("far_parent_build","end");
|
||||
std::printf("[ShapeSchedule] defer_far_parents=1 early_ready_s=%.6f far_shape_s=%.6f action=publish_before_lod2_tiles\n",
|
||||
std::chrono::duration<double>(Clock::now()-ColdStart).count(),
|
||||
DeferredFarShapeSeconds);
|
||||
MarkColdTimeline("lod2_queue","begin");
|
||||
Update=Streamer.UpdateDesiredWithSet(Desired,EarlyDesired.Tiles,0);
|
||||
MarkColdTimeline("lod2_queue","end");
|
||||
if(Update.DesiredTiles!=static_cast<int32>(Desired.Tiles.size()))
|
||||
{
|
||||
Streamer.Stop();
|
||||
@@ -5764,9 +5828,27 @@ namespace StandaloneStreamBenchmark
|
||||
if(ExpectedTilesByLOD[LOD]!=0)
|
||||
NearLODReadySeconds=std::max(NearLODReadySeconds,LODReadySeconds[LOD]);
|
||||
}
|
||||
double NearLODPublishedSeconds=0.0,NearLODPipelineSeconds=0.0;
|
||||
for(std::size_t LOD=0;LOD<=2;++LOD)
|
||||
{
|
||||
if(ExpectedTilesByLOD[LOD]==0)continue;
|
||||
NearLODPublishedSeconds=std::max(NearLODPublishedSeconds,
|
||||
LODPublishedReadySeconds[LOD]);
|
||||
NearLODPipelineSeconds=std::max(NearLODPipelineSeconds,
|
||||
LODPipelineReadySeconds[LOD]);
|
||||
std::printf("[WorldAssemblerLODPipelineReady] lod=%zu generated_s=%.6f scheduler_published_s=%.6f pipeline_drained_s=%.6f\n",
|
||||
LOD,LODReadySeconds[LOD],LODPublishedReadySeconds[LOD],
|
||||
LODPipelineReadySeconds[LOD]);
|
||||
}
|
||||
std::printf("[WorldAssemblerNearLODReady] lods=0-2 tiles=%llu/%llu cold_ready_s=%.6f\n",
|
||||
static_cast<unsigned long long>(NearLODCompleted),
|
||||
static_cast<unsigned long long>(NearLODExpected),NearLODReadySeconds);
|
||||
std::printf("[WorldAssemblerNearLODPublished] lods=0-2 tiles=%llu/%llu cold_ready_s=%.6f\n",
|
||||
static_cast<unsigned long long>(NearLODCompleted),
|
||||
static_cast<unsigned long long>(NearLODExpected),NearLODPublishedSeconds);
|
||||
std::printf("[WorldAssemblerNearLODPipelineReady] lods=0-2 tiles=%llu/%llu cold_ready_s=%.6f\n",
|
||||
static_cast<unsigned long long>(NearLODCompleted),
|
||||
static_cast<unsigned long long>(NearLODExpected),NearLODPipelineSeconds);
|
||||
for(std::size_t LOD=0;LOD<TileCountByLOD.size();++LOD)
|
||||
if(ExpectedTilesByLOD[LOD]!=0)
|
||||
std::printf("[WorldAssemblerLODReady] lod=%zu tiles=%llu cold_ready_s=%.6f\n",
|
||||
|
||||
@@ -54,6 +54,8 @@ struct FStandaloneCpuTile
|
||||
std::chrono::steady_clock::time_point QueuedAt{};
|
||||
std::chrono::steady_clock::time_point StartedAt{};
|
||||
std::chrono::steady_clock::time_point CompletedAt{};
|
||||
std::chrono::steady_clock::time_point PublishedAt{};
|
||||
std::chrono::steady_clock::time_point DrainedAt{};
|
||||
uint64 DensityHash=14695981039346656037ull;
|
||||
bool bHasDensityHash=false;
|
||||
uint64 MeshHash=14695981039346656037ull;
|
||||
@@ -362,8 +364,12 @@ struct FStandaloneTileJob
|
||||
|
||||
struct FStandaloneCpuTileTimelineEvent
|
||||
{
|
||||
enum class EType : uint8 { Queued, Dispatch, Finish };
|
||||
EType Type=EType::Queued;
|
||||
enum class EType : uint8
|
||||
{
|
||||
Requested, Admitted, Dispatch, Finish, Published, Drained,
|
||||
WorkerStart, WorkerIdleBegin, WorkerIdleEnd, WorkerStop
|
||||
};
|
||||
EType Type=EType::Admitted;
|
||||
FVoxelTileKey Key;
|
||||
int32 WorkerId=-1;
|
||||
size_t QueueDepth=0;
|
||||
@@ -517,6 +523,15 @@ public:
|
||||
bColdTimelineTrace=true;
|
||||
}
|
||||
|
||||
void RecordColdTimelineRequests(const std::vector<FVoxelTileKey>& Keys,
|
||||
std::chrono::steady_clock::time_point RequestedAt)
|
||||
{
|
||||
if(!bColdTimelineTrace)return;
|
||||
for(const FVoxelTileKey& Key:Keys)
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::Requested,Key,-1,
|
||||
0,0,0,RequestedAt,RequestedAt);
|
||||
}
|
||||
|
||||
void DumpColdTimelineTrace() const
|
||||
{
|
||||
if(!bColdTimelineTrace)return;
|
||||
@@ -532,16 +547,14 @@ public:
|
||||
Events.size(),WorkerCount);
|
||||
for(const auto& Event:Events)
|
||||
{
|
||||
const char* Type=Event.Type==FStandaloneCpuTileTimelineEvent::EType::Queued
|
||||
?"queued":Event.Type==FStandaloneCpuTileTimelineEvent::EType::Dispatch
|
||||
?"dispatch":"finish";
|
||||
const char* Type=TimelineEventName(Event.Type);
|
||||
std::printf("[CpuTileTimeline] event=%s key=(%d,%d,%d,lod%d) at_ms=%.3f frame=%llu worker_id=%d queue_depth=%zu active_workers=%zu priority_rank=%zu queued_ms=%.3f dispatch_ms=%.3f finish_ms=%.3f service_ms=%.3f worker_ms=%.3f\n",
|
||||
Type,Event.Key.Coord.X,Event.Key.Coord.Y,Event.Key.Coord.Z,Event.Key.Level,
|
||||
TimelineMilliseconds(Event.At),static_cast<unsigned long long>(TimelineFrame()),
|
||||
Event.WorkerId,Event.QueueDepth,Event.ActiveWorkers,Event.PriorityRank,
|
||||
TimelineMilliseconds(Event.QueuedAt),TimelineMilliseconds(Event.StartedAt),
|
||||
TimelineMilliseconds(Event.FinishedAt),
|
||||
Event.StartedAt.time_since_epoch().count()!=0
|
||||
Event.Type==FStandaloneCpuTileTimelineEvent::EType::Finish
|
||||
?std::chrono::duration<double,std::milli>(Event.At-Event.StartedAt).count():-1.0,
|
||||
Event.WorkerMilliseconds);
|
||||
if(Event.Type==FStandaloneCpuTileTimelineEvent::EType::Finish)
|
||||
@@ -747,7 +760,16 @@ public:
|
||||
std::vector<FStandaloneCpuTile> Out;
|
||||
std::lock_guard<std::mutex> Lock(Mutex);
|
||||
Out.swap(Ready);
|
||||
for(const FStandaloneCpuTile& Tile:Out)Outstanding.erase(Tile.Key);
|
||||
const FClock::time_point DrainedAt=FClock::now();
|
||||
for(FStandaloneCpuTile& Tile:Out)
|
||||
{
|
||||
Tile.DrainedAt=DrainedAt;
|
||||
Outstanding.erase(Tile.Key);
|
||||
if(bColdTimelineTrace)
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::Drained,
|
||||
Tile.Key,-1,Queue.size(),Running.size(),0,DrainedAt,
|
||||
Tile.QueuedAt,Tile.StartedAt,Tile.CompletedAt,Tile.WorkerSeconds*1000.0);
|
||||
}
|
||||
return Out;
|
||||
}
|
||||
|
||||
@@ -1083,7 +1105,7 @@ private:
|
||||
Job.QueuedAt=FClock::now();
|
||||
Queue.push_back(Job);
|
||||
if(bColdTimelineTrace)
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::Queued,Key,-1,
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::Admitted,Key,-1,
|
||||
Queue.size(),Running.size(),Job.PriorityRank,Job.QueuedAt,Job.QueuedAt);
|
||||
Outstanding.insert(Key);++Stats.NewJobs;
|
||||
if(Key.Level<=2)++NearOutstandingJobs;
|
||||
@@ -1278,6 +1300,9 @@ private:
|
||||
|
||||
void WorkerLoop(int32 WorkerId)
|
||||
{
|
||||
if(bColdTimelineTrace)
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::WorkerStart,{},
|
||||
WorkerId,0,0,0,FClock::now());
|
||||
constexpr uint32 PriorityTaskBurst=3;
|
||||
uint32 ConsecutivePriorityTasks=0;
|
||||
for(;;)
|
||||
@@ -1295,8 +1320,21 @@ private:
|
||||
return !Queue.empty()&&((SchedulerPolicy!=1&&!bStationaryNearGate)
|
||||
||NearOutstandingJobs==0||Queue.front().Key.Level<=2);
|
||||
};
|
||||
const bool bEnteringIdle=!bStop&&PriorityTasks.empty()&&!HasEligibleTile();
|
||||
if(bEnteringIdle&&bColdTimelineTrace)
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::WorkerIdleBegin,
|
||||
{},WorkerId,Queue.size(),Running.size(),0,FClock::now());
|
||||
Wake.wait(Lock,[&](){return bStop||!PriorityTasks.empty()||HasEligibleTile();});
|
||||
if(bStop)return;
|
||||
if(bEnteringIdle&&bColdTimelineTrace)
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::WorkerIdleEnd,
|
||||
{},WorkerId,Queue.size(),Running.size(),0,FClock::now());
|
||||
if(bStop)
|
||||
{
|
||||
if(bColdTimelineTrace)
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::WorkerStop,{},
|
||||
WorkerId,Queue.size(),Running.size(),0,FClock::now());
|
||||
return;
|
||||
}
|
||||
const bool bTileEligible=HasEligibleTile();
|
||||
const bool bPreferPriority=!PriorityTasks.empty()
|
||||
&&(!bTileEligible||ConsecutivePriorityTasks<PriorityTaskBurst);
|
||||
@@ -1335,7 +1373,20 @@ private:
|
||||
Tile.QueuedAt,Tile.StartedAt,Tile.CompletedAt,Tile.WorkerSeconds*1000.0,
|
||||
&Tile.CoreDiagnostics,Tile.DensitySamples,Tile.SkirtTriangleCount,
|
||||
Tile.PayloadBuildMilliseconds);
|
||||
const FVoxelTileKey PublishedKey=Tile.Key;
|
||||
const auto PublishedQueuedAt=Tile.QueuedAt;
|
||||
const auto PublishedStartedAt=Tile.StartedAt;
|
||||
const auto PublishedCompletedAt=Tile.CompletedAt;
|
||||
const double PublishedWorkerMs=Tile.WorkerSeconds*1000.0;
|
||||
const int32 PublishedWorkerId=Tile.WorkerId;
|
||||
Ready.push_back(std::move(Tile));
|
||||
const FClock::time_point PublishedAt=FClock::now();
|
||||
Ready.back().PublishedAt=PublishedAt;
|
||||
if(bColdTimelineTrace)
|
||||
RecordTimelineEvent(FStandaloneCpuTileTimelineEvent::EType::Published,
|
||||
PublishedKey,PublishedWorkerId,Queue.size(),Running.size(),Job.PriorityRank,
|
||||
PublishedAt,PublishedQueuedAt,PublishedStartedAt,PublishedCompletedAt,
|
||||
PublishedWorkerMs);
|
||||
}
|
||||
Wake.notify_all();
|
||||
}
|
||||
@@ -1351,6 +1402,24 @@ private:
|
||||
{
|
||||
return TimelineFrameOrdinal?TimelineFrameOrdinal->load(std::memory_order_relaxed):0;
|
||||
}
|
||||
static const char* TimelineEventName(FStandaloneCpuTileTimelineEvent::EType Type)
|
||||
{
|
||||
using EType=FStandaloneCpuTileTimelineEvent::EType;
|
||||
switch(Type)
|
||||
{
|
||||
case EType::Requested:return "requested";
|
||||
case EType::Admitted:return "admitted";
|
||||
case EType::Dispatch:return "started";
|
||||
case EType::Finish:return "finished";
|
||||
case EType::Published:return "published";
|
||||
case EType::Drained:return "drained";
|
||||
case EType::WorkerStart:return "worker_start";
|
||||
case EType::WorkerIdleBegin:return "idle_begin";
|
||||
case EType::WorkerIdleEnd:return "idle_end";
|
||||
case EType::WorkerStop:return "worker_stop";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
std::size_t PassageOverlapScore(const FVoxelTileKey& Key) const
|
||||
{
|
||||
const FIntVector Origin=Key.OriginVoxels();
|
||||
|
||||
Reference in new issue
Block a user