diff --git a/Standalone/BuildLinux.sh b/Standalone/BuildLinux.sh index 1f5c255..43ed044 100755 --- a/Standalone/BuildLinux.sh +++ b/Standalone/BuildLinux.sh @@ -86,6 +86,10 @@ fi if [[ "${VOXELFORGE_PROFILE_LEGACY_TERMS:-0}" == "1" ]]; then FLAGS+=(-DVF_L76_PROFILE_LEGACY_TERMS=1) fi +if [[ "${VOXELFORGE_PROFILE_L77:-0}" == "1" ]]; then + FLAGS+=(-DVF_L77_PROFILE=1 -g) + LINK_FLAGS+=(-no-pie) +fi if [[ "$($COMPILER --version | head -n 1)" == *clang* ]]; then FLAGS+=(-Wno-c++11-narrowing) else @@ -142,6 +146,11 @@ done < "$ROOT/Core/core_sources.txt" headless_object="$BUILD_DIR/objects/StreamBenchmarkHeadless.o" compile_background "$ROOT/Source/StreamBenchmarkHeadless.cpp" "$headless_object" LEGACY_OBJECTS+=("$headless_object") +if [[ "${VOXELFORGE_PROFILE_L77:-0}" == "1" ]]; then + l77_profiler_object="$BUILD_DIR/objects/Linux77Profiler.o" + compile_background "$ROOT/Source/Linux77Profiler.cpp" "$l77_profiler_object" + LEGACY_OBJECTS+=("$l77_profiler_object") +fi for pid in "${PIDS[@]}"; do wait "$pid"; done PIDS=() diff --git a/Standalone/Core/include/VoxelForgeCore/Linux77Profiler.h b/Standalone/Core/include/VoxelForgeCore/Linux77Profiler.h new file mode 100644 index 0000000..97ab442 --- /dev/null +++ b/Standalone/Core/include/VoxelForgeCore/Linux77Profiler.h @@ -0,0 +1,159 @@ +#pragma once + +#include +#include +#include + +namespace VoxelForgeCore::Linux77Profiler +{ + enum class ERoute : std::uint8_t + { + Dispatch=0,PackedScalar=1,PackedX8=2,AnalyticScalar=3, + AnalyticBatch=4,Native=5,LegacySurface=6,SharedSource=7,Count=8 + }; + enum class EStage : std::uint8_t + { + Other=0,GridFill=1,MarchingCubes=2,Skirt=3,Refine=4,Count=5 + }; + enum class EPhase : std::uint8_t + { + Dispatch=0,BaseField=1,CompositionGraph=2,Bands=3,Passage=4, + Support=5,Caps=6,Stamps=7,Edit=8,Other=9,Count=10 + }; + inline constexpr std::size_t RouteCount=static_cast(ERoute::Count); + inline constexpr std::size_t StageCount=static_cast(EStage::Count); + inline constexpr std::size_t PhaseCount=static_cast(EPhase::Count); + inline thread_local bool ThreadContextActive=false; + + struct FThreadContext + { + std::uint8_t lod=0xff; + ERoute route=ERoute::Count; + EStage stage=EStage::Other; + EPhase phase=EPhase::Other; + bool halo=false; + }; + +#if defined(VF_L77_PROFILE) + bool IsEnabled() noexcept; + void SetEnabled(bool enabled) noexcept; + void RegisterThread(); + void Start(std::uint32_t periodMicroseconds=1000); + void StopAndPrint(); + inline thread_local FThreadContext CurrentContext{}; + + struct FScopedRoute + { + explicit FScopedRoute(ERoute value) noexcept + :active(ThreadContextActive),previous(CurrentContext.route) + {if(active)CurrentContext.route=value;} + ~FScopedRoute(){if(active)CurrentContext.route=previous;} + bool active=false;ERoute previous=ERoute::Dispatch; + }; + struct FScopedStage + { + explicit FScopedStage(EStage value) noexcept + :active(ThreadContextActive),previous(CurrentContext.stage) + {if(active)CurrentContext.stage=value;} + ~FScopedStage(){Restore();} + void Restore() noexcept + {if(active){CurrentContext.stage=previous;active=false;}} + bool active=false;EStage previous=EStage::Other; + }; + struct FScopedPhase + { + explicit FScopedPhase(EPhase value) noexcept + :active(ThreadContextActive),previous(CurrentContext.phase) + {if(active)CurrentContext.phase=value;} + ~FScopedPhase(){if(active)CurrentContext.phase=previous;} + bool active=false;EPhase previous=EPhase::Dispatch; + }; + struct FScopedLod + { + explicit FScopedLod(int value) noexcept + :active(IsEnabled()),previous(CurrentContext.lod),previousContextActive(ThreadContextActive) + { + if(active) + { + ThreadContextActive=true; + RegisterThread(); + CurrentContext.lod=static_cast(value<0||value>8?0xff:value); + } + } + ~FScopedLod() + {if(active){CurrentContext.lod=previous;ThreadContextActive=previousContextActive;}} + bool active=false;std::uint8_t previous=0xff; + bool previousContextActive=false; + }; + struct FScopedHalo + { + explicit FScopedHalo(bool value) noexcept + :active(ThreadContextActive),previous(CurrentContext.halo) + {if(active)CurrentContext.halo=value;} + ~FScopedHalo(){if(active)CurrentContext.halo=previous;} + bool active=false;bool previous=false; + }; +#else + inline bool IsEnabled() noexcept{return false;} + inline void SetEnabled(bool) noexcept{} + inline void RegisterThread(){} + inline void Start(std::uint32_t=1000){} + inline void StopAndPrint(){} + struct FScopedRoute{explicit FScopedRoute(ERoute) noexcept{}}; + struct FScopedStage + {explicit FScopedStage(EStage) noexcept{}void Restore() noexcept{}}; + struct FScopedPhase{explicit FScopedPhase(EPhase) noexcept{}}; + struct FScopedLod{explicit FScopedLod(int) noexcept{}}; + struct FScopedHalo{explicit FScopedHalo(bool) noexcept{}}; +#endif + + struct FDispatchCounter + { + std::uint64_t calls=0; + std::uint64_t points=0; + }; + using FDispatchCounters=std::array,StageCount>; + + inline const char* RouteName(ERoute value) noexcept + { + switch(value) + { + case ERoute::Dispatch:return "dispatch_lookup"; + case ERoute::PackedScalar:return "packed_scalar"; + case ERoute::PackedX8:return "packed_x8"; + case ERoute::AnalyticScalar:return "analytic_scalar"; + case ERoute::AnalyticBatch:return "analytic_batch"; + case ERoute::Native:return "native"; + case ERoute::LegacySurface:return "legacy_surface"; + case ERoute::SharedSource:return "shared_source"; + default:return "unknown"; + } + } + inline const char* StageName(EStage value) noexcept + { + switch(value) + { + case EStage::GridFill:return "grid_fill"; + case EStage::MarchingCubes:return "marching_cubes"; + case EStage::Skirt:return "skirt"; + case EStage::Refine:return "refine"; + default:return "other"; + } + } + inline const char* PhaseName(EPhase value) noexcept + { + switch(value) + { + case EPhase::Dispatch:return "dispatch_lookup"; + case EPhase::BaseField:return "base_field"; + case EPhase::CompositionGraph:return "composition_graph"; + case EPhase::Bands:return "composition_bands"; + case EPhase::Passage:return "passages"; + case EPhase::Support:return "support"; + case EPhase::Caps:return "caps"; + case EPhase::Stamps:return "stamps"; + case EPhase::Edit:return "edits"; + default:return "other"; + } + } +} diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index 659139f..81c1a4e 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -11,6 +11,8 @@ #include #include +#include "VoxelForgeCore/Linux77Profiler.h" + // UBT supplies this export/import macro for the runtime module. The standalone target has no // module boundary, so leave it empty there. UBT fournit la macro; le viewer autonome reste neutre. #ifndef VOXELFORGECORE_API @@ -170,6 +172,13 @@ namespace VoxelForgeCore std::array legacyFieldTermCalls{}; std::array legacyFieldTermNanoseconds{}; std::array legacyFieldTermTimedCalls{}; + // Linux77-only mutually-exclusive route counts, flattened as + // (stage * route_count + route) * 2 + {calls,points}. + std::array linux77DispatchCounters{}; + std::uint64_t linux77GridInteriorSamples = 0; + std::uint64_t linux77GridHaloSamples = 0; std::uint64_t legacyPrimitiveCandidateVisits = 0; std::uint64_t legacyPrimitiveDistanceEvaluations = 0; std::uint64_t legacySmoothMinCalls = 0; @@ -1797,6 +1806,8 @@ namespace VoxelForgeCore // Research-only: collect tile-drain kernel counters and floating-island cache metrics. // Inactive on ordinary generation so the hot path only pays the option check. bool instrumentTileDrain = false; + // Linux headless measurement only. Compiled out of ordinary builds. + bool linux77Profile = false; bool exactMidpointDensityMemo = false; bool activeLaneBatching = false; std::uint32_t proofBlockCells = 8; diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h index fdc240e..e26c3ba 100644 --- a/Standalone/Core/src/ShapeWorldInternal.h +++ b/Standalone/Core/src/ShapeWorldInternal.h @@ -9,6 +9,7 @@ #include "VoxelForgeCore/VoxelForgeCore.h" #include "VoxelForgeFieldShared.h" #include "VoxelForgeCore/FloatingIslandInstrumentation.h" +#include "VoxelForgeCore/Linux77Profiler.h" #include #include @@ -988,6 +989,8 @@ public: float ApplyResolvedStratePassageCarves(float density,float X,float Y,float Z) const { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase( + VoxelForgeCore::Linux77Profiler::EPhase::Passage); if(!ResolvedLayout||ResolvedLayout->passages.empty()||!std::isfinite(X) ||!std::isfinite(Y)||!std::isfinite(Z))return density; constexpr double Q=static_cast(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); @@ -1028,6 +1031,8 @@ public: float deferredSupportDensity=std::numeric_limits::infinity(); const auto composeRouteMouthSupport=[&](std::size_t passageIndex) { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77MouthSupportPhase( + VoxelForgeCore::Linux77Profiler::EPhase::Support); // Surface-route treads may reinforce native solid terrain only. if(!(density<0.0f))return; if(passageIndex>=ResolvedLayout->passages.size() @@ -1882,8 +1887,14 @@ public: supportCenterIndex+1); selectedSupportSegmentIndex=supportCenterIndex>0 ?supportCenterIndex-1:supportCenterIndex; - for(std::ptrdiff_t index=supportBegin;index<=supportEnd;++index) - considerSupportSegment(index); + { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77SupportSearchPhase( + VoxelForgeCore::Linux77Profiler::EPhase::Support); + for(std::ptrdiff_t index=supportBegin;index<=supportEnd;++index) + considerSupportSegment(index); + } + VoxelForgeCore::Linux77Profiler::FScopedPhase l77SupportApplyPhase( + VoxelForgeCore::Linux77Profiler::EPhase::Support); // Keep route treads inside the native rock envelope. Carving may reopen the // floor above this point, but a support cannot create a new surface in air. const bool passageColumnFloorSupport=hasSupportFloor @@ -1994,6 +2005,8 @@ public: { float graphDensity=0.0f; { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77GraphPhase( + VoxelForgeCore::Linux77Profiler::EPhase::CompositionGraph); FScopedLegacyFieldTermTimer TermTimer(ELegacyFieldTerm::ComposerCavern); graphDensity=ApplyResolvedCavernGraph(density,X,Y,Z); } @@ -2009,6 +2022,8 @@ public: float boundary=graphDensity; if(!nativeLattice) { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77BandsPhase( + VoxelForgeCore::Linux77Profiler::EPhase::Bands); FScopedLegacyFieldTermTimer TermTimer(ELegacyFieldTerm::ComposerBoundary); boundary=ApplyResolvedStrateBoundaryBand(graphDensity,X,Y,Z); } @@ -2018,6 +2033,8 @@ public: float composed=boundary; if(!nativeLattice) { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase( + VoxelForgeCore::Linux77Profiler::EPhase::Passage); FScopedLegacyFieldTermTimer TermTimer( ELegacyFieldTerm::ComposerPassageAndSupport); composed=ApplyResolvedStratePassageCarves(boundary,X,Y,Z); @@ -2025,6 +2042,8 @@ public: float stamped=composed; if(!StampRuntime.empty()) { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77StampPhase( + VoxelForgeCore::Linux77Profiler::EPhase::Stamps); FScopedLegacyFieldTermTimer TermTimer(ELegacyFieldTerm::ComposerStamps); stamped=ApplyResolvedSdfStamps(composed,X,Y,Z); } @@ -2050,6 +2069,8 @@ public: // already combine each floor with its wall before the single void carve above. float final=0.0f; { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77CapsPhase( + VoxelForgeCore::Linux77Profiler::EPhase::Caps); FScopedLegacyFieldTermTimer TermTimer( ELegacyFieldTerm::ComposerPassageAndSupport); final=ApplyResolvedCavernFloorCaps(stamped,X,Y,Z); @@ -2230,6 +2251,7 @@ public: std::array LegacyFieldTermCalls{}; std::array LegacyFieldTermNanoseconds{}; std::array LegacyFieldTermTimedCalls{}; + VoxelForgeCore::Linux77Profiler::FDispatchCounters Linux77DispatchCounters{}; uint64 LegacyPrimitiveCandidateVisits=0,LegacyPrimitiveDistanceEvaluations=0; uint64 LegacySmoothMinCalls=0,LegacySmoothMinNanoseconds=0, LegacySmoothMinTimedCalls=0; @@ -2248,6 +2270,21 @@ public: {ThreadClassificationStats().CaptureDensityQueryProfile=Enabled;} static FClassificationThreadStats GetThreadClassificationStats() { return ThreadClassificationStats(); } + static void RecordLinux77Dispatch(VoxelForgeCore::Linux77Profiler::ERoute route, + uint64 points) + { +#if defined(VF_L77_PROFILE) + using namespace VoxelForgeCore::Linux77Profiler; + if(!ThreadContextActive)return; + const auto stage=static_cast(CurrentContext.stage); + const auto routeIndex=static_cast(route); + if(stage>=StageCount||routeIndex>=RouteCount)return; + auto& counter=ThreadClassificationStats().Linux77DispatchCounters[stage][routeIndex]; + ++counter.calls;counter.points+=points; +#else + (void)route;(void)points; +#endif + } enum class EDensityQueryKind : uint8 { Float=0,Lattice=1,Unclamped=2,X8=3 }; static uint32& DensityQuerySuppressionDepth() {static thread_local uint32 Depth=0;return Depth;} @@ -3400,8 +3437,14 @@ public: { if(SharedDensitySource)return SharedDensitySource->DensityAt(X,Y,Z); FScopedDensityQueryProfile queryProfile(EDensityQueryKind::Float); + using namespace VoxelForgeCore::Linux77Profiler; + FScopedRoute l77DispatchRoute(ERoute::Dispatch); + FScopedPhase l77DispatchPhase(EPhase::Dispatch); if(bNativeOnly) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); if(!NativeOnlyContains(X,Y,Z)) {RecordNativeOnlyViolation();return 0.0f;} float NativeDensity=0.0f; @@ -3412,22 +3455,41 @@ public: float IslandDensity=0.0f; if(NativeFloatingIslandDensityAt(X,Y,Z,IslandDensity)) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); ++ThreadClassificationStats().NativeFloatFieldCalls; return ApplyEditBrushes(ApplyResolvedStrateComposition(IslandDensity,X,Y,Z),X,Y,Z); } float NativeDensity=0.0f; if(NativeSurfaceDensityAt(X,Y,Z,NativeDensity)) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); ++ThreadClassificationStats().NativeFloatFieldCalls; return ApplyEditBrushes(ApplyResolvedStrateComposition(NativeDensity,X,Y,Z),X,Y,Z); } if(UsesLegacySurfaceField(X,Y,Z)) + { + RecordLinux77Dispatch(ERoute::LegacySurface,1); + FScopedRoute l77Route(ERoute::LegacySurface); + FScopedPhase l77Base(EPhase::BaseField); return LegacySurfaceDensityAt(X,Y,Z); + } int32 IX=0,IY=0,IZ=0; const bool bInteger=NearInteger(X,IX)&&NearInteger(Y,IY)&&NearInteger(Z,IZ); const bool bPacked=!bAnalyticOnly&&bInteger&&Contains(IX,IY,IZ); if(bPacked) + { + RecordLinux77Dispatch(ERoute::PackedScalar,1); + FScopedRoute l77Route(ERoute::PackedScalar); + FScopedPhase l77Base(EPhase::BaseField); return PackedDensityAt(IX,IY,IZ,IsRock(IX,IY,IZ),X,Y,Z); + } + RecordLinux77Dispatch(ERoute::AnalyticScalar,1); + FScopedRoute l77Route(ERoute::AnalyticScalar); + FScopedPhase l77Base(EPhase::BaseField); return AnalyticDensityAt(X,Y,Z); } @@ -3474,10 +3536,22 @@ public: float DensityAtLattice(int32 X,int32 Y,int32 Z) const { - if(SharedDensitySource)return SharedDensitySource->DensityAtLattice(X,Y,Z); + using namespace VoxelForgeCore::Linux77Profiler; + if(SharedDensitySource) + { + if(ThreadContextActive)RecordLinux77Dispatch(ERoute::SharedSource,1); + FScopedRoute l77Route(ERoute::SharedSource); + FScopedPhase l77Phase(EPhase::BaseField); + return SharedDensitySource->DensityAtLattice(X,Y,Z); + } FScopedDensityQueryProfile queryProfile(EDensityQueryKind::Lattice); + FScopedRoute l77DispatchRoute(ERoute::Dispatch); + FScopedPhase l77DispatchPhase(EPhase::Dispatch); if(bNativeOnly) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); if(!NativeOnlyContains(static_cast(X),static_cast(Y), static_cast(Z))) {RecordNativeOnlyViolation();return 0.0f;} @@ -3491,6 +3565,9 @@ public: if(NativeFloatingIslandDensityAt(static_cast(X),static_cast(Y), static_cast(Z),IslandDensity)) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); ++ThreadClassificationStats().NativeLatticeFieldCalls; return ApplyEditBrushes(ApplyResolvedStrateComposition(IslandDensity,X,Y,Z),X,Y,Z); } @@ -3498,13 +3575,21 @@ public: if(NativeSurfaceDensityAt(static_cast(X),static_cast(Y), static_cast(Z),NativeDensity)) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); ++ThreadClassificationStats().NativeLatticeFieldCalls; return ApplyEditBrushes(ApplyResolvedStrateComposition(NativeDensity,X,Y,Z),X,Y,Z); } if(UsesLegacySurfaceField(static_cast(X),static_cast(Y), static_cast(Z))) + { + RecordLinux77Dispatch(ERoute::LegacySurface,1); + FScopedRoute l77Route(ERoute::LegacySurface); + FScopedPhase l77Base(EPhase::BaseField); return LegacySurfaceDensityAt(static_cast(X),static_cast(Y), static_cast(Z)); + } const bool bPacked=!bAnalyticOnly&&Contains(X,Y,Z); static const bool bL75TraceTnDensity=[] { @@ -3545,18 +3630,38 @@ public: } } if(bPacked) + { + RecordLinux77Dispatch(ERoute::PackedScalar,1); + FScopedRoute l77Route(ERoute::PackedScalar); + FScopedPhase l77Base(EPhase::BaseField); return PackedDensityAt(X,Y,Z,IsRock(X,Y,Z),static_cast(X), static_cast(Y),static_cast(Z)); + } + RecordLinux77Dispatch(ERoute::AnalyticScalar,1); + FScopedRoute l77Route(ERoute::AnalyticScalar); + FScopedPhase l77Base(EPhase::BaseField); return AnalyticDensityAt(static_cast(X),static_cast(Y), static_cast(Z)); } float DensityAtUnclamped(float X,float Y,float Z) const { - if(SharedDensitySource)return SharedDensitySource->DensityAtUnclamped(X,Y,Z); + using namespace VoxelForgeCore::Linux77Profiler; + if(SharedDensitySource) + { + if(ThreadContextActive)RecordLinux77Dispatch(ERoute::SharedSource,1); + FScopedRoute l77Route(ERoute::SharedSource); + FScopedPhase l77Phase(EPhase::BaseField); + return SharedDensitySource->DensityAtUnclamped(X,Y,Z); + } FScopedDensityQueryProfile queryProfile(EDensityQueryKind::Unclamped); + FScopedRoute l77DispatchRoute(ERoute::Dispatch); + FScopedPhase l77DispatchPhase(EPhase::Dispatch); if(bNativeOnly) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); if(!NativeOnlyContains(X,Y,Z)) {RecordNativeOnlyViolation();return 0.0f;} float NativeDensity=0.0f; @@ -3567,17 +3672,31 @@ public: float IslandDensity=0.0f; if(NativeFloatingIslandDensityAt(X,Y,Z,IslandDensity)) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); ++ThreadClassificationStats().NativeUnclampedFieldCalls; return ApplyEditBrushes(ApplyResolvedStrateComposition(IslandDensity,X,Y,Z),X,Y,Z); } float NativeDensity=0.0f; if(NativeSurfaceDensityAt(X,Y,Z,NativeDensity)) { + RecordLinux77Dispatch(ERoute::Native,1); + FScopedRoute l77Route(ERoute::Native); + FScopedPhase l77Base(EPhase::BaseField); ++ThreadClassificationStats().NativeUnclampedFieldCalls; return ApplyEditBrushes(ApplyResolvedStrateComposition(NativeDensity,X,Y,Z),X,Y,Z); } if(UsesLegacySurfaceField(X,Y,Z)) + { + RecordLinux77Dispatch(ERoute::LegacySurface,1); + FScopedRoute l77Route(ERoute::LegacySurface); + FScopedPhase l77Base(EPhase::BaseField); return LegacySurfaceDensityAt(X,Y,Z); + } + RecordLinux77Dispatch(ERoute::AnalyticScalar,1); + FScopedRoute l77Route(ERoute::AnalyticScalar); + FScopedPhase l77Base(EPhase::BaseField); return AnalyticDensityAt(X,Y,Z,false); } @@ -3602,13 +3721,20 @@ public: void DensityAtLatticeX8(int32 XStart,int32 XStep,int32 Y,int32 Z, int32 Count,float OutDensity[8]) const { + using namespace VoxelForgeCore::Linux77Profiler; if(SharedDensitySource) { + if(ThreadContextActive&&Count>0)RecordLinux77Dispatch(ERoute::SharedSource, + static_cast(Count)); + FScopedRoute l77Route(ERoute::SharedSource); + FScopedPhase l77Phase(EPhase::BaseField); SharedDensitySource->DensityAtLatticeX8(XStart,XStep,Y,Z,Count,OutDensity); return; } Count=std::clamp(Count,0,8); if(Count==0)return; + FScopedRoute l77DispatchRoute(ERoute::Dispatch); + FScopedPhase l77DispatchPhase(EPhase::Dispatch); FScopedDensityQueryProfile queryProfile(EDensityQueryKind::X8, static_cast(Count)); FScopedDensityQueryBatch queryBatch(queryProfile.IsActive()); @@ -3681,6 +3807,10 @@ public: return; } + if(ThreadContextActive)RecordLinux77Dispatch(ERoute::PackedX8, + static_cast(Count)); + FScopedRoute l77PackedRoute(ERoute::PackedX8); + FScopedPhase l77PackedBase(EPhase::BaseField); const size_t ColumnStart=static_cast(Y-Min[1])*Size[0] +static_cast(XStart-Min[0]); const size_t Zi=static_cast(Z-Min[2]); @@ -7794,6 +7924,8 @@ private: float ApplyEditBrushes(float Density,double X,double Y,double Z) const { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77EditPhase( + VoxelForgeCore::Linux77Profiler::EPhase::Edit); if(EditBrushes.empty()||XEditBoundsMax.X ||YEditBoundsMax.Y||ZEditBoundsMax.Z) return Density; @@ -8492,6 +8624,8 @@ private: float ApplyResolvedCavernFloorCaps(float density,float X,float Y,float Z) const { + VoxelForgeCore::Linux77Profiler::FScopedPhase l77CapsPhase( + VoxelForgeCore::Linux77Profiler::EPhase::Caps); if(CavernRuntime.empty()||!Owner||Owner->CoreVoxelSizeMicrons==0)return density; const auto* tileQueries=ActivePassageTileQueries; const bool scoped=tileQueries&&tileQueries->matches(*this); @@ -11462,12 +11596,19 @@ public: void DensityAtLatticeZRun(int32 X,int32 Y,int32 ZStart,int32 ZStep, int32 Count,float* OutDensity) const { + using namespace VoxelForgeCore::Linux77Profiler; if(SharedDensitySource) { + if(ThreadContextActive&&Count>0)RecordLinux77Dispatch(ERoute::SharedSource, + static_cast(Count)); + FScopedRoute l77Route(ERoute::SharedSource); + FScopedPhase l77Phase(EPhase::BaseField); SharedDensitySource->DensityAtLatticeZRun(X,Y,ZStart,ZStep,Count,OutDensity); return; } if(Count<=0||OutDensity==nullptr)return; + FScopedRoute l77DispatchRoute(ERoute::Dispatch); + FScopedPhase l77DispatchPhase(EPhase::Dispatch); FScopedDensityQueryProfile queryProfile(EDensityQueryKind::Lattice, static_cast(Count)); FScopedDensityQueryBatch queryBatch(queryProfile.IsActive()); @@ -11513,6 +11654,10 @@ public: return; } + if(ThreadContextActive)RecordLinux77Dispatch(ERoute::AnalyticBatch, + static_cast(Count)); + FScopedRoute l77BatchRoute(ERoute::AnalyticBatch); + FScopedPhase l77BatchBase(EPhase::BaseField); FDetailNoiseLineContext DetailNoiseLine( static_cast(X),static_cast(Y),static_cast(Owner->Seed)); for(int32 Offset=0;Offset World::generateTile(const TileKey& key,const TileGenerationOptions& options, std::string& error) const { + VoxelForgeCore::Linux77Profiler::FScopedLod l77Lod(key.lod); // Fine owner tiles had zero direct-map conflict evictions in the cold audit. Keep their // single-probe path and use associativity for the coarse coordinate families that collide. // Les tuiles proches n'avaient aucun conflit; garder leur acces simple et associer les LOD grossiers. @@ -2162,6 +2163,22 @@ namespace VoxelForgeCore TileMesh out;out.key=key; const auto CopyIslandCacheMetrics=[&]() { + if(options.linux77Profile) + { + const auto& QueryCounts=FStandaloneShapeWorld::GetThreadClassificationStats(); + for(std::size_t Stage=0;Stage( std::chrono::steady_clock::now()-MeshingStart).count(); out.diagnostics.farHorizonVersion=key.lod>=4?options.farHorizonVersion:0; + VoxelForgeCore::Linux77Profiler::FScopedStage l77RefineStage( + VoxelForgeCore::Linux77Profiler::EStage::Refine); const auto FarShellStart=std::chrono::steady_clock::now(); const FStandaloneShapeWorld& farShape=tileShape.HasFarWorld()?tileShape: (bShapeReady?*impl_->shape:tileShape); @@ -2922,6 +2941,7 @@ namespace VoxelForgeCore AppendStratumBoundaryFloors(world,farShape,nativeKey,step,mesh); AppendStratumBoundaryCeilings(world,farShape,nativeKey,step,mesh); } + l77RefineStage.Restore(); out.densitySampleCount=static_cast(std::max(0,sampleCount)); if(bHasWorldAssembly) diff --git a/Standalone/Research/WorldAssemblerM3/Linux77/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux77/REPORT.md new file mode 100644 index 0000000..2eb38e2 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux77/REPORT.md @@ -0,0 +1,81 @@ +# Linux77 — FI/TN whole-view cost + +## Run and method + +Final profile runs were FI/TN r12 and r13, source stamp `6532cc3d9ca7137b1b62a3ae1c7bc54ebffc8fa3d58a9f12740c11d2048f4a0d`. They used eight workers, LOD0–8, `hash=off`, `force_generate=off`, and no `--stream-hash`; whole-tile skips remained active (481 FI, 578 TN). The route and phase tags are enabled only in the L77 build plus `--linux77-profile`. A separate default build with the profiler compiled out emitted zero samples. + +The sampler used a per-thread CPU timer on each worker and the main thread. It recorded one PC per timer delivery and expanded delayed signals by `1 + si_overrun`. Across four profiles it recorded 32,235 events / 128,923 weighted ticks, with nine timers per process, zero ring loss, and 129.06 s of profiled thread CPU. Handler CPU was 23.9 ms total (0.018%); per-run cost was 0.017–0.020%. The handler figure excludes kernel signal-delivery cost. The full per-call tag/counter overhead could not be isolated from run-to-run timing variation. + +## Cold readiness + +Times are from the two final profiled runs; values show mean (range). LOD readiness means every desired tile at that LOD completed. + +| Ready point | FI | TN | +|---|---:|---:| +| First tile | 0.377 s (0.376–0.377) | 0.399 s (0.388–0.409) | +| 27-tile neighborhood | 0.744 s (0.714–0.774) | 0.563 s (0.559–0.566) | +| LOD0 | 4.139 s (4.118–4.160) | 4.046 s (3.921–4.172) | +| LOD1 | 4.618 s (4.593–4.642) | 4.233 s (4.106–4.361) | +| LOD2 | 2.226 s (2.209–2.242) | 2.040 s (1.983–2.096) | +| LOD0–2 all ready | 4.618 s (4.593–4.642) | 4.234 s (4.106–4.361) | +| Whole view ready | 4.617 s (4.593–4.641) | 4.233 s (4.105–4.360) | + +LOD1 is last, so LOD0–2 completion and whole-view readiness coincide in these runs. The ~1 s target is met for the first tile and neighborhood, but not for complete LOD0–2. The compiled-out controls measured 4.54–5.55 s FI and 4.70–4.74 s TN for whole-view readiness; they emitted no sampler records. Their timing scatter is too large to infer a small instrumentation delta. This headless run measures readiness, not frame-time stutter. + +## Exclusive cost account + +Worker CPU is the sum of tile-worker time, averaged over r12/r13. Each cell is seconds (% of that scope); rounded values may not sum exactly. The phase split assigns field and composition work wherever it runs. MC, skirt, and refine columns contain the remaining non-field work in those caller stages, so composition inside a mesher call is not counted twice. `Other` is unclassified grid work plus the residual tile work. + +| Strate / scope | Worker CPU | Base packed / analytic / other | Graph | Bands | Passages | Support | Caps + edits | Dispatch | MC | Skirts | Refine | Other | +|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| +| FI LOD0–2 | 23.02 s | 0.45 (1.9%) / 0.29 (1.3%) / 0.00 | 0.03 (0.1%) | 0.52 (2.3%) | 15.17 (65.9%) | 3.26 (14.2%) | 0.06 (0.3%) | 0.84 (3.7%) | 0.36 (1.6%) | 0.02 (0.1%) | 1.73 (7.5%) | 0.30 (1.3%) | +| FI whole view | 33.87 s | 0.45 (1.3%) / 1.29 (3.8%) / 0.08 (0.2%) | 0.04 (0.1%) | 0.66 (2.0%) | 18.16 (53.6%) | 3.50 (10.3%) | 0.09 (0.3%) | 2.27 (6.7%) | 0.47 (1.4%) | 0.05 (0.2%) | 6.35 (18.8%) | 0.47 (1.4%) | +| TN LOD0–2 | 21.50 s | 0.31 (1.4%) / 0.41 (1.9%) / 0.00 | 0.02 (0.1%) | 0.57 (2.6%) | 14.07 (65.4%) | 2.90 (13.5%) | 0.05 (0.2%) | 0.78 (3.6%) | 0.26 (1.2%) | 0.04 (0.2%) | 1.85 (8.6%) | 0.25 (1.2%) | +| TN whole view | 30.63 s | 0.31 (1.0%) / 1.39 (4.5%) / 0.04 (0.1%) | 0.04 (0.1%) | 0.70 (2.3%) | 15.91 (52.0%) | 3.06 (10.0%) | 0.06 (0.2%) | 2.10 (6.8%) | 0.38 (1.2%) | 0.07 (0.2%) | 6.21 (20.3%) | 0.38 (1.2%) | + +“Base other” is native plus any other base route. Native appears at LOD4–8 in the whole view; legacy-surface and shared-source routes recorded no calls here. Analytic-batch also recorded no calls. + +### Route census and halo work + +[route-census.csv](route-census.csv) has exact route calls and points, plus expanded CPU time, for every LOD × caller-stage × route and the LOD0–2 / whole-view aggregates. Grid-fill points for LOD0–2 were: + +| Strate | Packed scalar | Packed X8 calls / points | Analytic scalar | Total grid points | +|---|---:|---:|---:|---:| +| FI | 10.519 M | 1.044 M / 6.319 M | 0.989 M | 17.827 M | +| TN | 6.639 M | 1.398 M / 8.423 M | 1.548 M | 16.610 M | + +Route-census time is exclusive by outer route and stage; composition time remains inside its packed/analytic route. The cost table is a separate, exclusive phase-first view of those same samples. `dispatch_lookup` and `unknown` rows have zero density-call counts by design. + +Halo counts are exact; halo CPU is its sampled share of grid fill and overlaps the cost categories above. FI LOD0–2: 1.534 M of 17.827 M points (8.6%), about 1.92 s CPU (8.4%). FI whole view: 2.524 M of 24.439 M (10.3%), about 2.65 s (7.8%). TN LOD0–2: 1.485 M of 16.610 M (8.9%), about 1.89 s (8.8%). TN whole view: 2.382 M of 22.604 M (10.5%), about 2.47 s (8.1%). The run recorded halo points, not a set of coordinates, so exact cross-tile duplicate-coordinate counts are unavailable. + +## Closure and sampled hotspots + +The grid estimate uses each LOD’s weighted `grid_fill` sample share of direct worker time; the comparison is direct `mc_grid_ms` timing: + +| Strate / scope | Sample estimate | Direct grid fill | Closure | +|---|---:|---:|---:| +| FI LOD0–2 | 19.051 s | 19.058 s | 99.96% | +| FI whole view | 23.931 s | 23.903 s | 100.11% | +| TN LOD0–2 | 17.365 s | 17.377 s | 99.93% | +| TN whole view | 20.818 s | 20.848 s | 99.86% | + +Every LOD0–2 bin closed within 1.4%. Sparse far bins were noisier (FI LOD7 reached +18%; TN LOD6 reached −17%), while the whole-view totals still closed within 0.15%. Those per-LOD tails are sample variance, not missing work in the target scopes. + +Top symbolized PC samples below are expanded-tick shares, grouped by `addr2line` leaf symbol; the `lower_bound` caller resolves into passage spatial-node visitation: + +| Sampled function | FI LOD0–2 / whole | TN LOD0–2 / whole | +|---|---:|---:| +| `VF_FieldValueNoise` | 16.6% / 12.8% | 17.0% / 12.9% | +| `std::lower_bound` in `VisitNearestPassageSpatialNode` | 14.2% / 11.4% | 11.5% / 9.2% | +| `ApplyResolvedStratePassageCarves` | 6.5% / 5.6% | 6.9% / 5.9% | +| `VF_FieldLerp` | 6.3% / 4.8% | 6.5% / 4.8% | + +## Biggest lever + +Passage carving is the largest phase: 65–66% of LOD0–2 CPU and 52–54% of whole-view CPU. A same-world 2× speedup in this phase would save about 7.0–7.6 worker CPU seconds for LOD0–2 and 8.0–9.1 seconds for the whole view: roughly one third of early CPU and one quarter of whole-view CPU. Removing the phase entirely is the measured hard ceiling (52–54% whole view); it is not a realistic target. + +## Failed or excluded runs + +The first `ITIMER_PROF` attempts (`fi-profile-r1`, `tn-profile-r1`) recorded 1,822 and 1,701 samples, all on the main thread (`lod=255`), and are excluded. All final r12/r13 profiles and compiled-out controls exited successfully; none timed out. + +No `--stream-hash` run was made, as required to keep skip behavior. The source diff adds only opt-in profiling tags, counters, and the sampler; generator and meshing formulas were not changed. Hash equality to `90378a5` was therefore not directly measured. diff --git a/Standalone/Research/WorldAssemblerM3/Linux77/RunLinux77.py b/Standalone/Research/WorldAssemblerM3/Linux77/RunLinux77.py new file mode 100644 index 0000000..208fd71 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux77/RunLinux77.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +"""Cold production-path samples and controls for Linux77.""" +from __future__ import annotations + +import json +import re +import subprocess +import sys +import time +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l77" +DATA = ROOT / "Standalone/data/owner_world.json" +BINARIES = { + "clean": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-l76-clang", + "clean_default": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-l77-clean-clang", + "l77_off": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-l77-clang", + "profile": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-l77-clang", +} +CAMERAS = { + "FI": (25.8369140625, 3.19921875, -737.0), + "TN": (19.166015625, -14.2001953125, -753.3740234375), +} +KV = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)") +PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M) +STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M) + + +def run(world: str, mode: str, replicate: int = 1) -> dict: + camera = ",".join(f"{value:.12f}" for value in CAMERAS[world]) + ",0,0" + name = f"{world.lower()}-{mode}-r{replicate}" + log = OUT / f"{name}.log" + command = [ + "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", "timeout", "1740s", + str(BINARIES[mode]), str(DATA), "--world-assembler-prototype", "--stream-benchmark", + "--stream-pipeline", "--workers=8", "--clip-radius=3", "--max-clip-level=8", + "--max-level=8", f"--camera={camera}", "--profile-lod-work", + ] + if mode == "profile": + command.append("--linux77-profile") + start = time.monotonic() + with log.open("w", encoding="utf-8") as output: + result = subprocess.run(command, cwd=ROOT, stdout=output, + stderr=subprocess.STDOUT, check=False, timeout=1740) + content = log.read_text(encoding="utf-8", errors="replace") + match = PIPELINE.search(content) + if result.returncode != 0 or match is None: + raise SystemExit(f"run failed or summary missing: {name} exit={result.returncode}; see {log}") + pipeline = dict(KV.findall(match.group(1))) + row = { + "world": world, + "mode": mode, + "replicate": replicate, + "exit_code": result.returncode, + "process_wall_s": round(time.monotonic() - start, 3), + "whole_view_ready_s": float(pipeline["whole_view_ready"].removesuffix("s")), + "stream_wall_s": float(pipeline["stream_wall"].removesuffix("s")), + "whole_tiles": int(pipeline["whole_tiles"].split("/")[0]), + "source_stamp": STAMP.search(content).group(1) if STAMP.search(content) else None, + "sampler_samples": sum(1 for line in content.splitlines() + if line.startswith("[L77Sample]")), + "sampler_header": next((line for line in content.splitlines() + if line.startswith("[L77Sampler] action=stop")), None), + "log": str(log.relative_to(ROOT)), + } + print("[Linux77Run] " + json.dumps(row, sort_keys=True), flush=True) + return row + + +def main() -> int: + OUT.mkdir(parents=True, exist_ok=True) + missing = [str(path) for path in [DATA, *BINARIES.values()] if not path.is_file()] + if missing: + raise SystemExit("missing input: " + ", ".join(missing)) + if len(sys.argv) > 1 and sys.argv[1] == "--clean-control": + schedule = [("FI", "clean_default", 14), ("TN", "clean_default", 14), + ("FI", "clean_default", 15), ("TN", "clean_default", 15)] + output_name = "final-clean-runs2.json" + else: + schedule = [("FI", "profile", 12), ("TN", "profile", 12), + ("FI", "profile", 13), ("TN", "profile", 13)] + output_name = "final-runs3.json" + rows = [run(*item) for item in schedule] + (OUT / output_name).write_text( + json.dumps(rows, indent=2) + "\n", encoding="utf-8") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Standalone/Research/WorldAssemblerM3/Linux77/route-census.csv b/Standalone/Research/WorldAssemblerM3/Linux77/route-census.csv new file mode 100644 index 0000000..30df2b5 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux77/route-census.csv @@ -0,0 +1,322 @@ +strate,lod_or_scope,caller_stage,route,calls,points,mean_worker_cpu_s,share_of_scope_worker_cpu_pct,time_expansion +FI,LOD0-2,grid_fill,analytic_scalar,989060,989060,1.5114677951400237,6.566324780297772,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,grid_fill,dispatch_lookup,0,0,0.8000038191830261,3.475485828494091,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,grid_fill,packed_scalar,10519492,10519492,16.471669627054567,71.55847633193315,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,grid_fill,packed_x8,1043578,6318749,0.017942194304907535,0.07794693043149986,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,grid_fill,unknown,0,0,0.256575564317475,1.1146506008357548,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,marching_cubes,analytic_scalar,175202,175202,0.5395186355015197,2.343850525374823,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,marching_cubes,dispatch_lookup,0,0,0.008270016079027356,0.03592773308686184,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,marching_cubes,unknown,0,0,0.35712034841945295,1.551450980904286,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,skirt,analytic_scalar,283132,283132,0.734197485785405,3.189600969366606,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,skirt,dispatch_lookup,0,0,0.011503486657390228,0.049975017490365085,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,skirt,packed_scalar,3461,3461,0.008451157575757576,0.03671467271107638,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,skirt,unknown,0,0,0.020237869981447124,0.08792011817050312,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,refine,analytic_scalar,410982,410982,0.45158734825818114,1.961847420680207,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,refine,dispatch_lookup,0,0,0.015495716872500495,0.06731860911330373,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,refine,packed_scalar,90,90,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,refine,unknown,0,0,1.7275706091619258,7.505148132913525,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,other,packed_scalar,21141,21141,0.04642743549593399,0.20169640475494585,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,LOD0-2,other,unknown,0,0,0.04043539021145856,0.1756649434412283,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,grid_fill,analytic_scalar,5497228,5497228,5.1183753527046,15.111741115899576,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,grid_fill,dispatch_lookup,0,0,1.6419819750415776,4.847867695105685,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,grid_fill,native,2103908,2103908,0.28169211464697264,0.8316815429892197,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,grid_fill,packed_scalar,10519492,10519492,16.471669627054567,48.63176105659098,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,grid_fill,packed_x8,1043578,6318749,0.017942194304907535,0.052973409862107614,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,grid_fill,unknown,0,0,0.3715942362473752,1.0971129531099177,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,marching_cubes,analytic_scalar,175202,175202,0.5395186355015197,1.5929011424678323,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,marching_cubes,dispatch_lookup,0,0,0.008270016079027356,0.024416798964255446,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,marching_cubes,unknown,0,0,0.4736148484194528,1.3983235860533134,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,skirt,analytic_scalar,540316,540316,0.8611306674290302,2.5424441969213967,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,skirt,dispatch_lookup,0,0,0.18731008673419514,0.5530234388980763,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,skirt,native,135583,135583,0.017509837442396314,0.05169689836661917,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,skirt,packed_scalar,3461,3461,0.008451157575757576,0.024951609957061437,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,skirt,unknown,0,0,0.0533177508186207,0.15741792887996894,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,refine,analytic_scalar,1357386,1357386,0.864707183378696,2.5530036771087334,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,refine,dispatch_lookup,0,0,0.4252432363323709,1.2555088784855217,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,refine,native,314164,314164,0.03753176927014705,0.11081062676117313,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,refine,packed_scalar,90,90,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,refine,unknown,0,0,6.352688817760581,18.755988412053558,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,other,packed_scalar,21141,21141,0.04642743549593399,0.13707462574407503,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,whole_view,other,unknown,0,0,0.09121255776227163,0.26930040578093506,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,grid_fill,dispatch_lookup,0,0,0.38031920901144944,2.3722071268932883,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,grid_fill,packed_scalar,6170132,6170132,12.464015990161606,77.74318746199104,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,grid_fill,packed_x8,460705,2947350,0.008017712734339533,0.05000976768757092,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,grid_fill,unknown,0,0,0.1543335880926037,0.9626419831485974,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,marching_cubes,analytic_scalar,175202,175202,0.5395186355015197,3.365199342823406,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,marching_cubes,dispatch_lookup,0,0,0.008270016079027356,0.05158348728475658,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,marching_cubes,unknown,0,0,0.20228234841945286,1.261718096786669,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,skirt,analytic_scalar,180361,180361,0.5422071030303031,3.3819684191179697,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,skirt,dispatch_lookup,0,0,0.008451157575757574,0.05271334120572065,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,skirt,packed_scalar,3446,3446,0.008451157575757576,0.05271334120572067,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,skirt,unknown,0,0,0.010628581818181817,0.06629483060662417,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,refine,analytic_scalar,278720,278720,0.3568117163401698,2.2255812391419214,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,refine,dispatch_lookup,0,0,0.005775156086394459,0.036022020719583624,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,refine,packed_scalar,64,64,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,refine,unknown,0,0,1.2757142698795203,7.957153914875125,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,other,packed_scalar,18225,18225,0.04053412562214352,0.2528279913422463,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,0,other,unknown,0,0,0.026962732071772143,0.16817763516974124,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,grid_fill,dispatch_lookup,0,0,0.30254916380202956,5.738461498231553,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,grid_fill,packed_scalar,4345294,4345294,4.005620947669902,75.97476488070637,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,grid_fill,packed_x8,571830,3335675,0.009924481570568,0.18823801945748772,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,grid_fill,unknown,0,0,0.09014090695749999,1.709706011052662,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,marching_cubes,unknown,0,0,0.14174800000000004,2.688539707826057,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,skirt,analytic_scalar,95786,95786,0.18649310775510203,3.5372218686364194,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,skirt,dispatch_lookup,0,0,0.002053704081632653,0.03895268343534887,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,skirt,packed_scalar,15,15,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,skirt,unknown,0,0,0.007941688163265306,0.1506303014794632,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,refine,analytic_scalar,104518,104518,0.07495393191801134,1.4216540777948492,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,refine,dispatch_lookup,0,0,0.00798631078610603,0.15147666046424346,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,refine,packed_scalar,26,26,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,refine,unknown,0,0,0.42526053928240554,8.065932824676677,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,other,packed_scalar,2916,2916,0.005893309873790466,0.11177863254655468,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,1,other,unknown,0,0,0.01173840813968641,0.2226428336922955,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,grid_fill,analytic_scalar,989060,989060,1.5114677951400237,88.1900064059472,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,grid_fill,dispatch_lookup,0,0,0.11713544636954706,6.834532498085309,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,grid_fill,packed_scalar,4066,4066,0.002032689223057644,0.11860184926146335,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,grid_fill,packed_x8,11043,35724,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,grid_fill,unknown,0,0,0.012101069267371325,0.7060642506838343,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,marching_cubes,unknown,0,0,0.013090000000000032,0.7637656505588374,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,skirt,analytic_scalar,6985,6985,0.005497274999999999,0.32075094092252265,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,skirt,dispatch_lookup,0,0,0.000998625,0.058267033826533005,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,skirt,unknown,0,0,0.0016676,0.09729989296194912,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,refine,analytic_scalar,27744,27744,0.01982170000000001,1.156541909524987,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,refine,dispatch_lookup,0,0,0.001734250000000005,0.1011887379283166,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,refine,unknown,0,0,0.02659579999999997,1.5517920923707145,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,2,other,unknown,0,0,0.0017342500000000032,0.1011887379283165,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,grid_fill,analytic_scalar,1392377,1392377,2.2608447138265086,90.33723611510052,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,grid_fill,dispatch_lookup,0,0,0.10981625579079163,4.387960379577972,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,grid_fill,unknown,0,0,0.01992853038269981,0.7962901404059265,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,marching_cubes,unknown,0,0,0.02844249999999988,1.1364853244851856,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,skirt,analytic_scalar,30338,30338,0.03122883333333333,1.2478196636767955,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,skirt,dispatch_lookup,0,0,0.0019113333333333335,0.07637170725262174,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,skirt,unknown,0,0,0.0019113333333333335,0.07637170725262174,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,refine,analytic_scalar,27744,27744,0.013041538961039033,0.5211046018431115,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,refine,unknown,0,0,0.03383288961038974,1.351870705006079,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,3,other,unknown,0,0,0.0017140714285714433,0.0684896553991671,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,grid_fill,analytic_scalar,1039680,1039680,0.6753226483383894,40.783025236761546,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,grid_fill,dispatch_lookup,0,0,0.31027948781945214,18.73791174237274,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,grid_fill,native,825968,825968,0.13335209963918002,8.05319066129514,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,grid_fill,unknown,0,0,0.03932376420297849,2.374779036125162,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,marching_cubes,unknown,0,0,0.034649,2.092468014963541,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,skirt,analytic_scalar,21920,21920,0.01872344761904762,1.130717055981483,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,skirt,dispatch_lookup,0,0,0.02462261904761905,1.4869705562000317,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,skirt,native,16880,16880,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,skirt,unknown,0,0,0.0015114333333333333,0.09127610917341705,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,refine,analytic_scalar,73366,73366,0.02859640863177226,1.7269494185924776,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,refine,dispatch_lookup,0,0,0.004416645546372818,0.2667231244542784,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,refine,native,19114,19114,0.008609716253443523,0.519944468187893,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,refine,unknown,0,0,0.3695238989898989,22.315707218129866,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,4,other,unknown,0,0,0.006960330578512419,0.42033735776241493,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,grid_fill,analytic_scalar,693120,693120,0.17292014736842104,12.590757929081375,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,grid_fill,dispatch_lookup,0,0,0.13962145263157896,10.166194850883814,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,grid_fill,native,623808,623808,0.05955472631578948,4.336331850199049,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,grid_fill,unknown,0,0,0.01858067368421053,1.352906344792248,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,marching_cubes,unknown,0,0,0.016031499999999962,1.1672944929315363,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,skirt,analytic_scalar,62052,62052,0.017873625000000004,1.301424322815924,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,skirt,dispatch_lookup,0,0,0.028636,2.085060356148056,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,skirt,native,21920,21920,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,skirt,unknown,0,0,0.010762375000000001,0.783636033332132,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,refine,analytic_scalar,83034,83034,0.036689881760247164,2.671484073545572,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,refine,dispatch_lookup,0,0,0.001977883771929825,0.14401477308002025,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,refine,native,14070,14070,0.001977883771929825,0.14401477308002025,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,refine,unknown,0,0,0.8646097697219408,62.954447352476535,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,5,other,unknown,0,0,0.004153580973952464,0.30243284763371675,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,grid_fill,analytic_scalar,363888,363888,0.11463918354866495,7.540682320096151,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,grid_fill,dispatch_lookup,0,0,0.07112330335917313,4.678315211130949,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,grid_fill,native,294576,294576,0.02930471800172265,1.9275919636778225,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,grid_fill,unknown,0,0,0.010477295090439277,0.6891705907637348,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,marching_cubes,unknown,0,0,0.010433999999999999,0.6863227466591592,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,skirt,analytic_scalar,27030,27030,0.0032961964285714287,0.21681565903634792,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,skirt,dispatch_lookup,0,0,0.030905035714285718,2.032856909816752,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,skirt,native,21504,21504,0.008376767857142857,0.551003097933721,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,refine,analytic_scalar,413600,413600,0.1432282536316259,9.421200731421525,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,refine,dispatch_lookup,0,0,0.3741994301373801,24.613914193039957,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,refine,native,223017,223017,0.01022790259201331,0.6727661682492726,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,refine,unknown,0,0,0.7094547744374726,46.666182616674384,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,6,other,unknown,0,0,0.004609139201507961,0.30317779150022506,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,grid_fill,analytic_scalar,190608,190608,0.0780883588007737,6.566731962616496,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,grid_fill,dispatch_lookup,0,0,0.047518221953578334,3.995978807870349,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,grid_fill,native,138624,138624,0.023615063588007735,1.9858759390529657,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,grid_fill,unknown,0,0,0.012742855657640231,1.0715927294044432,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,marching_cubes,unknown,0,0,0.0033875000000000025,0.28486710266400167,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,skirt,analytic_scalar,21486,21486,0.018595714285714285,1.5637807381664972,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,skirt,dispatch_lookup,0,0,0.018483,1.554302187022506,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,skirt,native,21294,21294,0.0031180714285714284,0.2622098815517481,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,skirt,unknown,0,0,0.0030617142857142857,0.25747060597975235,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,refine,analytic_scalar,83217,83217,0.049842317796610164,4.1914204164660465,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,refine,dispatch_lookup,0,0,0.0020813347457627114,0.1750269516455615,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,refine,native,13887,13887,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,refine,unknown,0,0,0.9203071822033899,77.39195293140988,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,7,other,unknown,0,0,0.00830966525423732,0.6987897461497589,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,grid_fill,analytic_scalar,828495,828495,0.30509250568181817,11.68786786683771,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,grid_fill,dispatch_lookup,0,0,0.16361943430397727,6.268139311773288,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,grid_fill,native,220932,220932,0.03586550710227272,1.3739810063563767,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,grid_fill,unknown,0,0,0.013965552911931817,0.5350099857654982,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,marching_cubes,unknown,0,0,0.023550000000000015,0.9021830531330275,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,skirt,analytic_scalar,94358,94358,0.03721536497695853,1.4256930615020114,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,skirt,dispatch_lookup,0,0,0.07124861198156682,2.729481540935045,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,skirt,native,53985,53985,0.006014998156682027,0.23043012320955078,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,skirt,unknown,0,0,0.015833024884792626,0.6065514535411212,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,refine,analytic_scalar,265443,265443,0.1417214343392203,5.429243156116755,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,refine,dispatch_lookup,0,0,0.027072225258424884,1.037116893365215,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,refine,native,44076,44076,0.016716266652760395,0.6403877913279481,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,refine,unknown,0,0,1.7273896936355628,66.17501943756503,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +FI,8,other,unknown,0,0,0.02503038011403147,0.9588953185714274,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,grid_fill,analytic_scalar,1547814,1547814,2.787883672864558,12.964298899381628,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,grid_fill,dispatch_lookup,0,0,0.7503316473939825,3.489214361833811,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,grid_fill,packed_scalar,6639057,6639057,13.59487596754143,63.21929327923922,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,grid_fill,packed_x8,1398161,8422843,0.025915570062882285,0.1205133484274309,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,grid_fill,unknown,0,0,0.21775764213714574,1.0126230114148986,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,marching_cubes,analytic_scalar,157327,157327,0.5659293754440966,2.6317014768621863,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,marching_cubes,dispatch_lookup,0,0,0.004151043928944623,0.019303306936048058,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,marching_cubes,unknown,0,0,0.25708908062695934,1.1955232269754204,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,skirt,analytic_scalar,278960,278960,0.7515375742601755,3.494822198522369,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,skirt,dispatch_lookup,0,0,0.007754216218347484,0.03605888501143833,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,skirt,packed_scalar,3440,3440,0.007953901959146163,0.03698746953411984,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,skirt,unknown,0,0,0.03642580756233081,0.1693883649041172,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,refine,analytic_scalar,447986,447986,0.5567071777222419,2.5888161409570216,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,refine,dispatch_lookup,0,0,0.013438340161686407,0.06249136585697526,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,refine,packed_scalar,78,78,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,refine,unknown,0,0,1.854369398514411,8.623243281706072,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,other,packed_scalar,13851,13851,0.03840051418431334,0.17857120389239714,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,LOD0-2,other,unknown,0,0,0.033794069417346806,0.1571501785448493,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,grid_fill,analytic_scalar,6247312,6247312,5.369497198034171,17.52789758555956,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,grid_fill,dispatch_lookup,0,0,1.4649254876203979,4.782023897300268,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,grid_fill,native,1295268,1295268,0.09096359233816967,0.29693665378981016,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,grid_fill,packed_scalar,6639057,6639057,13.59487596754143,44.37838122621452,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,grid_fill,packed_x8,1398161,8422843,0.025915570062882285,0.08459739174459352,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,grid_fill,unknown,0,0,0.3013736844029476,0.9837880308665723,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,marching_cubes,analytic_scalar,157327,157327,0.5659293754440966,1.847389386305195,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,marching_cubes,dispatch_lookup,0,0,0.004151043928944623,0.013550444329561803,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,marching_cubes,unknown,0,0,0.37453808062695926,1.2226219470837711,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,skirt,analytic_scalar,546945,546945,0.8644257680510252,2.821784940732287,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,skirt,dispatch_lookup,0,0,0.1493754359895893,0.48761313159496444,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,skirt,native,118410,118410,0.019686403921568625,0.06426323714100149,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,skirt,packed_scalar,3440,3440,0.007953901959146163,0.02596428935590782,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,skirt,unknown,0,0,0.06594249007867067,0.21525911458877,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,refine,analytic_scalar,1404455,1404455,0.9081680820980149,2.964574995833111,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,refine,dispatch_lookup,0,0,0.4655408017905882,1.5196863309049042,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,refine,native,280979,280979,0.031056844104054918,0.10138028994332285,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,refine,packed_scalar,78,78,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,refine,unknown,0,0,6.2132313849142875,20.282138042651972,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,other,packed_scalar,13851,13851,0.03840051418431334,0.12535257120571608,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,whole_view,other,unknown,0,0,0.07805437290874048,0.2547964928541846,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,grid_fill,dispatch_lookup,0,0,0.35453322577047847,2.2231872423616283,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,grid_fill,packed_scalar,5410312,5410312,12.26532025081103,76.91268835473244,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,grid_fill,packed_x8,550130,3504725,0.006001420924574209,0.037633376692860876,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,grid_fill,unknown,0,0,0.13371610249391727,0.8384995017512137,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,marching_cubes,analytic_scalar,157327,157327,0.5659293754440966,3.5487984654491176,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,marching_cubes,dispatch_lookup,0,0,0.004151043928944623,0.026030135497897875,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,marching_cubes,unknown,0,0,0.1479900806269594,0.928007970285196,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,skirt,analytic_scalar,175138,175138,0.5801641457454363,3.638061071691767,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,skirt,dispatch_lookup,0,0,0.005904695810184218,0.03702683822284732,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,skirt,packed_scalar,3420,3420,0.007953901959146163,0.04987688621888637,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,skirt,unknown,0,0,0.017811256485233302,0.1116898369746499,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,refine,analytic_scalar,278728,278728,0.46838929008395425,2.9371495207831546,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,refine,dispatch_lookup,0,0,0.007945521298174437,0.049824333235976494,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,refine,packed_scalar,56,56,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,refine,unknown,0,0,1.321453425663156,8.286496677215037,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,other,packed_scalar,10935,10935,0.03189667357584772,0.2000158874065751,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,0,other,unknown,0,0,0.027909589378866756,0.17501390148075324,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,grid_fill,dispatch_lookup,0,0,0.2049078060815429,8.579510952236802,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,grid_fill,packed_scalar,1224214,1224214,1.3295557167304008,55.66863484331164,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,grid_fill,packed_x8,836430,4879175,0.017908299394062552,0.7498223407172327,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,grid_fill,unknown,0,0,0.05584517779399359,2.3382433479499176,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,marching_cubes,unknown,0,0,0.08732150000000002,3.656160201713409,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,skirt,analytic_scalar,92395,92395,0.15685488684807256,6.56753027305054,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,skirt,dispatch_lookup,0,0,0.0018495204081632652,0.07743961004544435,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,skirt,packed_scalar,20,20,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,skirt,unknown,0,0,0.014761592743764172,0.6180694090648007,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,refine,analytic_scalar,104522,104522,0.06550360582010581,2.742642724508782,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,refine,dispatch_lookup,0,0,0.0020179126984126976,0.08449021258760576,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,refine,packed_scalar,22,22,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,refine,unknown,0,0,0.4413276911375661,18.478435897817103,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,other,packed_scalar,2916,2916,0.006503840608465624,0.2723164763656091,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,1,other,unknown,0,0,0.003981449735449753,0.1667037106311019,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,grid_fill,analytic_scalar,1547814,1547814,2.787883672864558,87.97621869706954,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,grid_fill,dispatch_lookup,0,0,0.19089061554196107,6.023864877719979,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,grid_fill,packed_scalar,4531,4531,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,grid_fill,packed_x8,11601,38943,0.0020058497442455242,0.06329786191971376,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,grid_fill,unknown,0,0,0.028196361849234904,0.8897822103033319,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,marching_cubes,unknown,0,0,0.021777499999999915,0.6872245500497622,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,skirt,analytic_scalar,11427,11427,0.014518541666666666,0.45815627433147804,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,skirt,unknown,0,0,0.0038529583333333332,0.12158638764713543,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,refine,analytic_scalar,64736,64736,0.022814281818181847,0.7199418921918747,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,refine,dispatch_lookup,0,0,0.0034749061650992726,0.10965633455518317,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,refine,unknown,0,0,0.09158828171368871,2.8902176875454404,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,2,other,unknown,0,0,0.0019030303030303022,0.060053226666562605,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,grid_fill,analytic_scalar,1653019,1653019,1.6257892599972985,84.05786681446597,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,grid_fill,dispatch_lookup,0,0,0.14083694920065815,7.281665471504162,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,grid_fill,unknown,0,0,0.02577929080204317,1.3328616728672036,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,marching_cubes,unknown,0,0,0.02774599999999998,1.434546057118157,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,skirt,analytic_scalar,28072,28072,0.0167755,0.8673404231667865,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,refine,analytic_scalar,55488,55488,0.021592010869565234,1.1163675505725947,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,refine,dispatch_lookup,0,0,0.002119250000000004,0.10957117175620494,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,refine,unknown,0,0,0.06925423913043482,3.580638495036522,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,3,other,unknown,0,0,0.004238500000000006,0.2191423435124098,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,grid_fill,analytic_scalar,1005024,1005024,0.2811271212461729,32.27756733129226,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,grid_fill,dispatch_lookup,0,0,0.16179719518272428,18.576720162660983,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,grid_fill,native,311904,311904,0.026100773337241874,2.996756289671185,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,grid_fill,unknown,0,0,0.02574141023386099,2.955496070044059,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,marching_cubes,unknown,0,0,0.035111499999999976,4.0313214901818935,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,skirt,analytic_scalar,34945,34945,0.01891341666666667,2.171541035304609,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,skirt,dispatch_lookup,0,0,0.01134805,1.3029246211827654,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,skirt,native,12288,12288,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,skirt,unknown,0,0,0.005533033333333333,0.6352743739959681,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,refine,analytic_scalar,69360,69360,0.03276482873303167,3.7618887883912633,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,refine,dispatch_lookup,0,0,0.002201970588235294,0.25281891554338065,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,refine,unknown,0,0,0.26812623009049774,30.784872006188262,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,4,other,unknown,0,0,0.0022019705882352913,0.2528189155433804,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,grid_fill,analytic_scalar,658464,658464,0.16022197444444444,15.70301020746246,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,grid_fill,dispatch_lookup,0,0,0.10012317333333334,9.812856309557121,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,grid_fill,native,329232,329232,0.016071991666666667,1.575181245088378,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,grid_fill,unknown,0,0,0.017855360555555554,1.7499653841741398,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,marching_cubes,unknown,0,0,0.016458499999999987,1.6130620933593305,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,skirt,analytic_scalar,62052,62052,0.023293805555555557,2.2829756509857932,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,skirt,dispatch_lookup,0,0,0.006777930555555556,0.6642903576017634,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,skirt,native,9216,9216,0,0.0,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,skirt,unknown,0,0,0.004773263888888889,0.46781730052967263,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,refine,analytic_scalar,69360,69360,0.03080573545881503,3.019203701836131,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,refine,dispatch_lookup,0,0,0.002047484375,0.20066952833235244,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,5,refine,unknown,0,0,0.641897280166185,62.91096822107287,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,grid_fill,analytic_scalar,363888,363888,0.11459216666666668,7.500616366774231,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,grid_fill,dispatch_lookup,0,0,0.08549591666666667,5.596124852999252,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,grid_fill,native,294576,294576,0.02641691666666667,1.7291160755000208,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,marching_cubes,unknown,0,0,0.010406999999999996,0.681188922416332,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,skirt,analytic_scalar,27030,27030,0.011539066666666667,0.7552882087399717,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,skirt,dispatch_lookup,0,0,0.020647266666666664,1.351464334727522,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,skirt,native,21504,21504,0.007287566666666667,0.47700679203457763,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,skirt,unknown,0,0,0.0045541,0.29808806299377527,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,refine,analytic_scalar,413600,413600,0.07480055929464402,4.8960615337808715,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,refine,dispatch_lookup,0,0,0.4078854146914068,26.698090333715598,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,refine,native,223017,223017,0.010105119747335176,0.6614293871024549,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,refine,unknown,0,0,0.7520207164626924,49.22342476044774,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,6,other,unknown,0,0,0.002018189803921655,0.1321003687676584,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,grid_fill,analytic_scalar,190608,190608,0.09132488562753037,7.717216629283747,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,grid_fill,dispatch_lookup,0,0,0.0567381032388664,4.794533612829431,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,grid_fill,native,138624,138624,0.006032866396761134,0.5097946365814808,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,grid_fill,unknown,0,0,0.0019801447368421056,0.16732794995080713,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,marching_cubes,unknown,0,0,0.003406499999999994,0.2878590897433347,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,skirt,analytic_scalar,21486,21486,0.0021386666666666668,0.1807235109147452,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,skirt,dispatch_lookup,0,0,0.030514,2.5785211402988786,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,skirt,native,21294,21294,0.0042773333333333335,0.3614470218294904,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,skirt,unknown,0,0,0.006155000000000001,0.520115278840519,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,refine,analytic_scalar,83217,83217,0.0502434782696837,4.245719043079463,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,refine,dispatch_lookup,0,0,0.01255071152207882,1.060571376596741,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,refine,native,13887,13887,0.010438610177714809,0.8820927121510345,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,refine,unknown,0,0,0.9055197308675271,76.51903287014713,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,7,other,unknown,0,0,0.0020714691629956095,0.17504512775320843,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,grid_fill,analytic_scalar,828495,828495,0.3085581171875,11.899177884558837,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,grid_fill,dispatch_lookup,0,0,0.16960250260416665,6.5405193891787485,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,grid_fill,native,220932,220932,0.016341044270833334,0.6301729942172918,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,grid_fill,unknown,0,0,0.012259835937499998,0.47278603455819074,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,marching_cubes,unknown,0,0,0.024319500000000004,0.9378526781315603,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,skirt,analytic_scalar,94400,94400,0.040227738235294117,1.5513350208329098,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,skirt,dispatch_lookup,0,0,0.0723339725490196,2.789473873845794,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,skirt,native,54108,54108,0.008121503921568627,0.3131961678200253,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,skirt,unknown,0,0,0.008501285294117648,0.3278419860872421,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,refine,analytic_scalar,265444,265444,0.14125429175003335,5.447304254419109,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,refine,dispatch_lookup,0,0,0.02529763045218087,0.9755731191003244,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,refine,native,44075,44075,0.010513114179004935,0.4054257812982444,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,refine,unknown,0,0,1.7220437896825396,66.40857665715129,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks +TN,8,other,unknown,0,0,0.033730173936241115,1.3007641588004308,1ms timer weighted by 1+si_overrun; grid/MC/skirt direct; remainder split refine/other by weighted stage ticks; route split by weighted ticks diff --git a/Standalone/Source/Linux77Profiler.cpp b/Standalone/Source/Linux77Profiler.cpp new file mode 100644 index 0000000..6782295 --- /dev/null +++ b/Standalone/Source/Linux77Profiler.cpp @@ -0,0 +1,257 @@ +#define _GNU_SOURCE 1 +#include "VoxelForgeCore/Linux77Profiler.h" + +#if defined(VF_L77_PROFILE) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace VoxelForgeCore::Linux77Profiler +{ + namespace + { + constexpr std::uint32_t Capacity=1u<<20; + constexpr std::size_t MaxRegisteredThreads=32; + struct FSample + { + std::uintptr_t pc=0; + std::uint8_t lod=0xff,route=0,stage=0,phase=0,halo=0,weight=1; + }; + static_assert(std::atomic::is_always_lock_free); + static_assert(std::atomic::is_always_lock_free); + std::array Samples{}; + std::atomic NextSample{0}; + std::atomic LostSamples{0},HandlerSamples{0},HandlerNanoseconds{0}; + std::atomic ExpandedTicks{0}; + std::atomic Enabled{false}; + volatile sig_atomic_t TimerActive=0; + std::atomic ActiveHandlers{0}; + std::uint32_t PeriodMicroseconds=1000; + std::mutex TimerRegistryMutex; + std::array ThreadTimers{}; + std::array ThreadIds{}; + std::array ThreadCpuClockIds{}; + std::array ThreadCpuStartNanoseconds{}; + std::array ThreadProfileCpuNanoseconds{}; + std::array,MaxRegisteredThreads> ThreadSampleCounts{}; + std::size_t ThreadTimerCount=0; + inline thread_local bool ThreadTimerRegistered=false; + std::atomic TimerOverruns{0}; + + std::uint64_t ThreadCpuNanoseconds() noexcept + { + timespec time{}; + if(clock_gettime(CLOCK_THREAD_CPUTIME_ID,&time)!=0)return 0; + return static_cast(time.tv_sec)*1000000000ull + +static_cast(time.tv_nsec); + } + std::uint64_t UserCpuNanoseconds(const timeval& value) noexcept + { + return static_cast(value.tv_sec)*1000000000ull + +static_cast(value.tv_usec)*1000ull; + } + void SigprofHandler(int, siginfo_t* information, void* context) noexcept + { + if(!TimerActive)return; + ActiveHandlers.fetch_add(1,std::memory_order_relaxed); + const std::uint64_t start=ThreadCpuNanoseconds(); + HandlerSamples.fetch_add(1,std::memory_order_relaxed); + const int timerIndex=information?information->si_value.sival_int:-1; + if(timerIndex>=0&&static_cast(timerIndex)(timerIndex)].fetch_add( + 1,std::memory_order_relaxed); + if(information&&information->si_overrun>0) + TimerOverruns.fetch_add(static_cast(information->si_overrun), + std::memory_order_relaxed); + } + const std::uint32_t index=NextSample.fetch_add(1,std::memory_order_relaxed); + const std::uint64_t overrun=information&&information->si_overrun>0 + ?static_cast(information->si_overrun):0; + const std::uint8_t weight=static_cast( + std::min(255,overrun+1)); + ExpandedTicks.fetch_add(weight,std::memory_order_relaxed); + if(index( + static_cast(context)->uc_mcontext.gregs[REG_RIP]); +#endif + const FThreadContext& tag=CurrentContext; + Samples[index]={pc,tag.lod,static_cast(tag.route), + static_cast(tag.stage), + static_cast(tag.phase),static_cast(tag.halo),weight}; + } + else LostSamples.fetch_add(1,std::memory_order_relaxed); + const std::uint64_t end=ThreadCpuNanoseconds(); + if(end>=start)HandlerNanoseconds.fetch_add(end-start,std::memory_order_relaxed); + ActiveHandlers.fetch_sub(1,std::memory_order_relaxed); + } + } + + bool IsEnabled() noexcept{return Enabled.load(std::memory_order_relaxed);} + void SetEnabled(bool enabled) noexcept{Enabled.store(enabled,std::memory_order_relaxed);} + + void RegisterThread() + { + if(ThreadTimerRegistered||!IsEnabled())return; + std::lock_guard lock(TimerRegistryMutex); + if(ThreadTimerRegistered||!IsEnabled()||ThreadTimerCount>=MaxRegisteredThreads)return; + struct sigevent event{}; + event.sigev_notify=SIGEV_THREAD_ID; + event.sigev_signo=SIGPROF; + event.sigev_value.sival_int=static_cast(ThreadTimerCount); + event._sigev_un._tid=static_cast(syscall(SYS_gettid)); + timer_t timer{}; + if(timer_create(CLOCK_THREAD_CPUTIME_ID,&event,&timer)!=0) + { + std::fprintf(stderr,"[L77SamplerError] action=thread_timer_create errno=%d\n",errno); + return; + } + itimerspec interval{}; + interval.it_value.tv_nsec=static_cast(PeriodMicroseconds%1000000u)*1000l; + interval.it_value.tv_sec=static_cast(PeriodMicroseconds/1000000u); + interval.it_interval=interval.it_value; + const std::size_t timerIndex=ThreadTimerCount; + clockid_t threadCpuClock{}; + if(pthread_getcpuclockid(pthread_self(),&threadCpuClock)!=0) + { + timer_delete(timer); + std::fprintf(stderr,"[L77SamplerError] action=thread_clock errno=%d\n",errno); + return; + } + timespec threadCpuStart{}; + if(clock_gettime(threadCpuClock,&threadCpuStart)!=0) + { + timer_delete(timer); + std::fprintf(stderr,"[L77SamplerError] action=thread_clock_read errno=%d\n",errno); + return; + } + ThreadCpuClockIds[timerIndex]=threadCpuClock; + ThreadCpuStartNanoseconds[timerIndex]= + static_cast(threadCpuStart.tv_sec)*1000000000ull + +static_cast(threadCpuStart.tv_nsec); + ThreadIds[timerIndex]=static_cast(event._sigev_un._tid); + if(timer_settime(timer,0,&interval,nullptr)!=0) + { + timer_delete(timer); + std::fprintf(stderr,"[L77SamplerError] action=thread_timer_start errno=%d\n",errno); + return; + } + ThreadTimers[ThreadTimerCount++]=timer; + ThreadTimerRegistered=true; + } + + void Start(std::uint32_t periodMicroseconds) + { + if(TimerActive)return; + PeriodMicroseconds=periodMicroseconds?periodMicroseconds:1000; + NextSample.store(0,std::memory_order_relaxed); + LostSamples.store(0,std::memory_order_relaxed); + HandlerSamples.store(0,std::memory_order_relaxed); + HandlerNanoseconds.store(0,std::memory_order_relaxed); + ExpandedTicks.store(0,std::memory_order_relaxed); + TimerOverruns.store(0,std::memory_order_relaxed); + struct sigaction action{}; + action.sa_sigaction=&SigprofHandler; + action.sa_flags=SA_SIGINFO|SA_RESTART; + sigemptyset(&action.sa_mask); + if(sigaction(SIGPROF,&action,nullptr)!=0) + { + std::fprintf(stderr,"[L77SamplerError] action=install errno=%d\n",errno); + return; + } + SetEnabled(true); + TimerActive=1; + RegisterThread(); + std::printf("[L77Sampler] action=start method=thread_cpu_timer period_us=%u capacity=%u\n", + PeriodMicroseconds,Capacity); + } + + void StopAndPrint() + { + if(!TimerActive)return; + SetEnabled(false); + std::size_t registeredThreadCount=0; + std::uint64_t profiledThreadCpuNanoseconds=0; + { + std::lock_guard lock(TimerRegistryMutex); + registeredThreadCount=ThreadTimerCount; + for(std::size_t index=0;index(now.tv_sec) + *1000000000ull+static_cast(now.tv_nsec) + -ThreadCpuStartNanoseconds[index]; + ThreadProfileCpuNanoseconds[index]=elapsed; + profiledThreadCpuNanoseconds+=elapsed; + } + timer_delete(ThreadTimers[index]); + } + ThreadTimerCount=0; + } + TimerActive=0; + while(ActiveHandlers.load(std::memory_order_relaxed)!=0){} + rusage usage{}; + getrusage(RUSAGE_SELF,&usage); + const std::uint64_t userNs=UserCpuNanoseconds(usage.ru_utime); + const std::uint64_t systemNs=UserCpuNanoseconds(usage.ru_stime); + const std::uint32_t stored=std::min(NextSample.load(std::memory_order_relaxed),Capacity); + const std::uint64_t handlerCount=HandlerSamples.load(std::memory_order_relaxed); + const std::uint64_t handlerNs=HandlerNanoseconds.load(std::memory_order_relaxed); + const std::uint64_t expandedTicks=ExpandedTicks.load(std::memory_order_relaxed); + std::printf("[L77Sampler] action=stop samples=%u handlers=%llu expanded_ticks=%llu lost=%llu timer_overruns=%llu timer_threads=%zu requested_period_us=%u profiled_thread_cpu_s=%.6f whole_process_cpu_s=%.6f handler_cpu_ms=%.3f handler_share_pct=%.3f observed_us_per_tick=%.3f status=%s\n", + stored,static_cast(handlerCount), + static_cast(expandedTicks), + static_cast(LostSamples.load(std::memory_order_relaxed)), + static_cast(TimerOverruns.load(std::memory_order_relaxed)), + registeredThreadCount,PeriodMicroseconds, + static_cast(profiledThreadCpuNanoseconds)/1.0e9, + static_cast(userNs+systemNs)/1.0e9, + static_cast(handlerNs)/1.0e6, + profiledThreadCpuNanoseconds?100.0*static_cast(handlerNs) + /static_cast(profiledThreadCpuNanoseconds):0.0, + expandedTicks?static_cast(profiledThreadCpuNanoseconds) + /static_cast(expandedTicks)/1000.0:0.0, + stored>0&&handlerCount>0?"PASS":"NO_SAMPLES"); + for(std::size_t index=0;index(ThreadIds[index]), + static_cast(ThreadProfileCpuNanoseconds[index])/1.0e6, + static_cast(ThreadSampleCounts[index].load( + std::memory_order_relaxed))); + for(std::uint32_t index=0;index(sample.route); + const auto stage=static_cast(sample.stage); + const auto phase=static_cast(sample.phase); + std::printf("[L77Sample] pc=0x%" PRIxPTR " lod=%u stage=%s route=%s phase=%s halo=%u weight=%u\n", + sample.pc,static_cast(sample.lod),StageName(stage), + RouteName(route),PhaseName(phase),static_cast(sample.halo), + static_cast(sample.weight)); + } + std::fflush(stdout); + } +} + +#endif diff --git a/Standalone/Source/StreamBenchmarkHeadless.cpp b/Standalone/Source/StreamBenchmarkHeadless.cpp index 0285e79..6e22a7c 100644 --- a/Standalone/Source/StreamBenchmarkHeadless.cpp +++ b/Standalone/Source/StreamBenchmarkHeadless.cpp @@ -49,6 +49,7 @@ namespace bool ProfileLodWork=false; bool ProfilePassageComposer=false; bool InstrumentTileDrain=false; + bool Linux77Profile=false; bool ExactMidpointDensityMemo=false; bool ActiveLaneBatching=false; bool ParallelSignEdgeRepair=false; @@ -1442,6 +1443,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" + " --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" " --active-lane-batching --proof-block-cells=N (proof-masked density fill A/B)\n" @@ -1500,6 +1502,8 @@ 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=="--linux77-profile") + {options.Linux77Profile=true;options.ProfileLodWork=true;} else if(arg=="--profile-passage-composer") {options.ProfilePassageComposer=true;options.InstrumentTileDrain=true;} else if(arg=="--exact-midpoint-density-memo")options.ExactMidpointDensityMemo=true; @@ -2224,5 +2228,5 @@ int main(int argc,char** argv) ?options.ParallelSignEdgeRepair:options.FloatingIslandsRecipe, options.AuditNativeLattice,options.LatticeOrphanControl, options.CaptureSkipWalkability,options.ProfilePassageComposer, - options.StreamHashAllowUniformSkips); + options.StreamHashAllowUniformSkips,options.Linux77Profile); } diff --git a/Standalone/Source/StreamBenchmarkPipeline.h b/Standalone/Source/StreamBenchmarkPipeline.h index e72b646..fda4e7f 100644 --- a/Standalone/Source/StreamBenchmarkPipeline.h +++ b/Standalone/Source/StreamBenchmarkPipeline.h @@ -1873,7 +1873,8 @@ namespace StandaloneStreamBenchmark bool bActiveLaneBatching=false,int32 ProofBlockCells=8, bool bParallelSignEdgeRepair=false,bool bAuditNativeLattice=false, bool bLatticeOrphanControl=false,bool bCaptureSkipWalkability=false, - bool bProfilePassageComposer=false,bool bAllowUniformSkipsWhenHashing=false) + bool bProfilePassageComposer=false,bool bAllowUniformSkipsWhenHashing=false, + bool bLinux77Profile=false) { using Clock=std::chrono::steady_clock; FStandaloneOwnerWorld& World=*OwnerWorld; @@ -2039,11 +2040,12 @@ namespace StandaloneStreamBenchmark bAllowUniformSkipsWhenHashing); Streamer.SetUniformBlockProofAuditEnabled(bAuditUniformBlockProofs); Streamer.SetTileDrainInstrumentationEnabled(bInstrumentTileDrain); + Streamer.SetLinux77ProfileEnabled(bLinux77Profile); Streamer.SetPassageComposerProfilingEnabled(bProfilePassageComposer); Streamer.SetExactMidpointDensityMemoEnabled(bExactMidpointDensityMemo); Streamer.SetActiveLaneBatchingEnabled(bActiveLaneBatching); Streamer.SetProofBlockCells(ProofBlockCells); - if(bScreenSpaceGate||bReportLodWorkProfile||bInstrumentTileDrain) + if(bScreenSpaceGate||bReportLodWorkProfile||bInstrumentTileDrain||bLinux77Profile) Streamer.SetMesherStageProfilingEnabled(true); if(bInstrumentTileDrain) { @@ -2053,6 +2055,7 @@ namespace StandaloneStreamBenchmark bExactMidpointDensityMemo?"on":"off", bParallelSignEdgeRepair?"on":"off"); } + if(bLinux77Profile)VoxelForgeCore::Linux77Profiler::Start(1000); const auto StreamStart=Clock::now(); const FStandaloneStreamingUpdate EarlyUpdate=Streamer.StartWithDesired(ShapeFreeDesired); if(EarlyUpdate.DesiredTiles!=static_cast(ShapeFreeDesired.Tiles.size())) @@ -5051,6 +5054,13 @@ namespace StandaloneStreamBenchmark std::unique_ptr FarLODProfile; if(bReportLodWorkProfile)FarLODProfile=std::make_unique(); std::array DensitySamplesByLOD{}; + using FL77Route=VoxelForgeCore::Linux77Profiler::ERoute; + using FL77Stage=VoxelForgeCore::Linux77Profiler::EStage; + std::array,9> L77DispatchByLOD{}; + std::array L77GridInteriorByLOD{},L77GridHaloByLOD{}; + std::array L77LODReadySeconds{}; std::array SkirtTrianglesByLOD{}; std::array TileCountByLOD{}; std::array ClassifiedAirTilesByLOD{},ClassifiedSolidTilesByLOD{}; @@ -5117,8 +5127,19 @@ namespace StandaloneStreamBenchmark if(Tile.Key.Level>=0&&Tile.Key.Level(TileCountByLOD.size())) { const std::size_t LOD=static_cast(Tile.Key.Level); - ++TileCountByLOD[LOD]; const auto& TileDiagnostics=Tile.CoreDiagnostics; + ++TileCountByLOD[LOD]; + if(bLinux77Profile) + { + const auto& D=TileDiagnostics; + for(std::size_t Counter=0;Counter( + Clock::now()-ColdStart).count(); + } if(TileDiagnostics.tileWasClassified) { switch(TileDiagnostics.tileClass) @@ -5500,6 +5521,36 @@ namespace StandaloneStreamBenchmark MovingMcOtherMsByLOD[LOD]); } } + if(bLinux77Profile) + { + VoxelForgeCore::Linux77Profiler::StopAndPrint(); + for(std::size_t LOD=0;LOD(ExpectedTilesByLOD[LOD]), + L77LODReadySeconds[LOD]); + std::printf("[WorldAssemblerL77GridSamples] lod=%zu interior=%llu halo=%llu\n", + LOD,static_cast(L77GridInteriorByLOD[LOD]), + static_cast(L77GridHaloByLOD[LOD])); + for(std::size_t Stage=0;Stage(Stage)), + VoxelForgeCore::Linux77Profiler::RouteName( + static_cast(Route)), + static_cast(Calls), + static_cast(Points)); + } + } + } Streamer.Stop(); Streamer.DumpColdTimelineTrace(); bool bScreenSpaceGatePassing=true; diff --git a/Standalone/Source/StreamingWorld.h b/Standalone/Source/StreamingWorld.h index 37c5024..13eeca9 100644 --- a/Standalone/Source/StreamingWorld.h +++ b/Standalone/Source/StreamingWorld.h @@ -714,6 +714,8 @@ public: {bProfileMesherStages=Enabled;} void SetTileDrainInstrumentationEnabled(bool Enabled) {bInstrumentTileDrain=Enabled;} + void SetLinux77ProfileEnabled(bool Enabled) + {bLinux77Profile=Enabled;} void SetPassageComposerProfilingEnabled(bool Enabled) {bProfilePassageComposer=Enabled;} void SetExactMidpointDensityMemoEnabled(bool Enabled) @@ -902,6 +904,7 @@ private: Options.profileMesherStages=(bProfileMesherStages||bInstrumentTileDrain)&&!ForceGenerate; Options.profilePassageComposer=bProfilePassageComposer; Options.instrumentTileDrain=bInstrumentTileDrain&&!ForceGenerate; + Options.linux77Profile=bLinux77Profile; Options.exactMidpointDensityMemo=bExactMidpointDensityMemo&&!ForceGenerate; Options.activeLaneBatching=bActiveLaneBatching&&!ForceGenerate; Options.proofBlockCells=static_cast(ProofBlockCells); @@ -1195,6 +1198,7 @@ private: int32 Lod8HorizonInteriorStepVoxels=0; bool bProfileMesherStages=false; bool bInstrumentTileDrain=false; + bool bLinux77Profile=false; bool bProfilePassageComposer=false; bool bExactMidpointDensityMemo=false; bool bActiveLaneBatching=false; diff --git a/Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp b/Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp index 6f0f9a2..2eca0c6 100644 --- a/Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp +++ b/Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp @@ -5,6 +5,7 @@ #include "VoxelHybridSharpMesher.h" #include "MarchingCubesTables.h" #include "StandaloneShapeWorld.h" +#include "VoxelForgeCore/Linux77Profiler.h" #include "VoxelDensityProfile.h" #if WITH_EDITOR #include "VoxelRedefinedDensityField.h" @@ -1047,6 +1048,8 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels, // Bande de strate : seules les rangées Z réellement lues (cellules CzLo..CzHi + marges de // gradient) sont échantillonnées — le reste du tampon reste non initialisé et non lu. const uint64 StageDensityGridStartCycles=OutStageTimings?FPlatformTime::Cycles64():0; + VoxelForgeCore::Linux77Profiler::FScopedStage l77GridFillStage( + VoxelForgeCore::Linux77Profiler::EStage::GridFill); VoxelDensityProfile::FScopedTimer MesherDensityGridTimer( VoxelDensityProfile::EBucket::MesherDensityGrid); #if WITH_EDITOR @@ -1264,6 +1267,7 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels, const int32 SampleZ=OriginVoxels.Z+gz*Step; const bool bBoundarySample=gx<0||gx>GridDim||gy<0||gy>GridDim ||gz<0||gz>GridDim; + VoxelForgeCore::Linux77Profiler::FScopedHalo l77Halo(bBoundarySample); VoxelForgeCore::floating_island_detail::FScopedIslandFieldCaller islandCaller( bBoundarySample ?VoxelForgeCore::floating_island_detail::EIslandFieldCaller::Boundary @@ -1272,6 +1276,11 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels, ?ShapeWorldContext->DensityAtLattice(SampleX,SampleY,SampleZ) :Generator->GetDensityAtLattice(SampleX,SampleY,SampleZ, bCapturePreEditGrid ? &PreEditDensity : nullptr); + if(OutStageTimings) + { + if(bBoundarySample)++OutStageTimings->DensityGridHaloSamples; + else ++OutStageTimings->DensityGridInteriorSamples; + } if (bCapturePreEditGrid) { OutPreEditDensityGrid->Samples[LocalIndex] = PreEditDensity; @@ -1304,6 +1313,7 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels, float Densities[8]{}; const bool bBoundarySample=GX0<0||GX0+BatchCount-1>GridDim ||gy<0||gy>GridDim||gz<0||gz>GridDim; + VoxelForgeCore::Linux77Profiler::FScopedHalo l77Halo(bBoundarySample); VoxelForgeCore::floating_island_detail::FScopedIslandFieldCaller islandCaller( bBoundarySample ?VoxelForgeCore::floating_island_detail::EIslandFieldCaller::Boundary @@ -1314,6 +1324,14 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels, { ++OutStageTimings->X8DensityCalls; OutStageTimings->X8ActiveLanes+=static_cast(BatchCount); + for(int32 Lane=0;LaneGridDim||gy<0||gy>GridDim + ||gz<0||gz>GridDim) + ++OutStageTimings->DensityGridHaloSamples; + else ++OutStageTimings->DensityGridInteriorSamples; + } } for(int32 Lane=0;LaneGridDim||gy<0||gy>GridDim ||GzLo<0||GzHi>GridDim; + VoxelForgeCore::Linux77Profiler::FScopedHalo l77Halo(bBoundarySample); VoxelForgeCore::floating_island_detail::FScopedIslandFieldCaller islandCaller( bBoundarySample ?VoxelForgeCore::floating_island_detail::EIslandFieldCaller::Boundary :VoxelForgeCore::floating_island_detail::EIslandFieldCaller::GridFill); ActiveShapeWorld->DensityAtLatticeZRun(SampleX,SampleY, OriginVoxels.Z+GzLo*Step,Step,BatchCount,Densities); + if(OutStageTimings) + { + for(int32 Lane=0;LaneGridDim||gy<0||gy>GridDim + ||LocalGz<0||LocalGz>GridDim) + ++OutStageTimings->DensityGridHaloSamples; + else ++OutStageTimings->DensityGridInteriorSamples; + } + } for(int32 Lane=0;LaneGridDim||gy<0||gy>GridDim; + VoxelForgeCore::Linux77Profiler::FScopedHalo l77Halo(bBoundarySample); VoxelForgeCore::floating_island_detail::FScopedIslandFieldCaller islandCaller( bBoundarySample ?VoxelForgeCore::floating_island_detail::EIslandFieldCaller::Boundary @@ -1527,6 +1558,9 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels, } } MesherDensityGridTimer.End(); + l77GridFillStage.Restore(); + VoxelForgeCore::Linux77Profiler::FScopedStage l77MarchingCubesStage( + VoxelForgeCore::Linux77Profiler::EStage::MarchingCubes); if(OutStageTimings) OutStageTimings->DensityGridMilliseconds=static_cast( FPlatformTime::Cycles64()-StageDensityGridStartCycles) @@ -2119,6 +2153,9 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels, const int32 CapSurfaceTriangleCount=CapTris.Num()/3; TArray GroundSkirtFaceMasks,CapSkirtFaceMasks; const uint64 SkirtStageStartCycles=OutStageTimings?FPlatformTime::Cycles64():0; + l77MarchingCubesStage.Restore(); + VoxelForgeCore::Linux77Profiler::FScopedStage l77SkirtStage( + VoxelForgeCore::Linux77Profiler::EStage::Skirt); VoxelForgeCore::floating_island_detail::FScopedIslandFieldCaller skirtFieldCaller( VoxelForgeCore::floating_island_detail::EIslandFieldCaller::Skirt); if (bGenerateSkirts && (GroundTris.Num() + CapTris.Num()) > 0) @@ -2382,6 +2419,9 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels, OutStageTimings->SkirtMilliseconds=static_cast( FPlatformTime::Cycles64()-SkirtStageStartCycles) *FPlatformTime::GetSecondsPerCycle64()*1000.0; + l77SkirtStage.Restore(); + VoxelForgeCore::Linux77Profiler::FScopedStage l77MesherFinalStage( + VoxelForgeCore::Linux77Profiler::EStage::MarchingCubes); // F17 — concatène sol PUIS sky-cap : un run d'indices contigu par polygroup (voir // FVoxelMeshData::NumCeilingTriangles). Mêmes triangles qu'avant, seul l'ordre change. diff --git a/Standalone/Source/VoxelForge/Public/VoxelMarchingCubesMesher.h b/Standalone/Source/VoxelForge/Public/VoxelMarchingCubesMesher.h index 503caed..11b6f33 100644 --- a/Standalone/Source/VoxelForge/Public/VoxelMarchingCubesMesher.h +++ b/Standalone/Source/VoxelForge/Public/VoxelMarchingCubesMesher.h @@ -59,6 +59,8 @@ struct FVoxelMarchingCubesStageTimings uint64 GradientMemoHits = 0; uint64 X8DensityCalls = 0; uint64 X8ActiveLanes = 0; + uint64 DensityGridInteriorSamples = 0; + uint64 DensityGridHaloSamples = 0; uint64 CandidateCells = 0; uint64 ZBandRejectedCells = 0; uint64 CellClassificationCalls = 0;