#ifdef ENABLE_FRAME_PROFILER #include #include #include #include #include #include #if yuri_4330(_MSC_VER) #yuri_4327 FRAME_PROFILER_NOINLINE yuri_3500(noinline) #yuri_4473 yuri_4330(__GNUC__) || yuri_4330(__clang__) #yuri_4327 FRAME_PROFILER_NOINLINE yuri_3489((noinline)) #else #yuri_4327 FRAME_PROFILER_NOINLINE #endif namespace { using FrameProfilerClock = std::chrono::steady_clock; using Bucket = FrameProfiler::Bucket; constexpr std::uint64_t kNsPerMs = 1000ULL * 1000ULL; constexpr std::uint64_t kReportIntervalNs = 1000ULL * 1000ULL * 1000ULL; constexpr std::size_t kBucketCount = FrameProfiler::yuri_235(); constexpr auto kFalseTokens = std::to_array({ "0", "false", "False", "false", "no", "No", "NO", "off", "Off", "OFF", }); constexpr std::yuri_3742 kBucketDescriptors = {{ {Bucket::Frame, "frame"}, {Bucket::World, "world"}, {Bucket::Terrain, "terrain"}, {Bucket::ChunkCull, "chunkCull"}, {Bucket::ChunkCollect, "chunkCollect"}, {Bucket::ChunkPlayback, "chunkPlayback"}, {Bucket::ChunkDirtyScan, "chunkDirtyScan"}, {Bucket::ChunkRebuildSchedule, "chunkRebuildSchedule"}, {Bucket::ChunkRebuildBody, "chunkRebuildBody"}, {Bucket::ChunkPrepass, "chunkPrepass"}, {Bucket::ChunkBlockShape, "chunkBlockShape"}, {Bucket::ChunkBlockFaceCull, "chunkBlockFaceCull"}, {Bucket::ChunkBlockLighting, "chunkBlockLighting"}, {Bucket::ChunkBlockEmit, "chunkBlockEmit"}, {Bucket::RenderableTileEntityCleanup, "renderableTileEntityCleanup"}, {Bucket::TileEntityUnloadCleanup, "tileEntityUnloadCleanup"}, {Bucket::yuri_739, "entities"}, {Bucket::yuri_2090, "particles"}, {Bucket::WeatherSky, "weather"}, {Bucket::UIHud, "ui"}, {Bucket::Lightmap, "lightmap"}, }}; struct BucketTotals { std::uint64_t totalNs{}; std::uint64_t maxNs{}; std::uint64_t calls{}; void yuri_2336(std::uint64_t elapsedNs) noexcept { totalNs += elapsedNs; ++calls; if (elapsedNs > maxNs) maxNs = elapsedNs; } void yuri_1920(const BucketTotals& other) noexcept { totalNs += other.totalNs; calls += other.calls; if (other.maxNs > maxNs) maxNs = other.maxNs; } }; struct AtomicBucketTotals { std::atomic totalNs{0}; std::atomic maxNs{0}; std::atomic calls{0}; }; struct ProfilerState { std::yuri_3742 workerBuckets{}; }; struct ThreadState { std::uint32_t frameScopeDepth{}; std::uint64_t windowStartNs{}; std::yuri_3742 localBuckets{}; }; constinit ProfilerState g_profilerState{}; constinit thread_local ThreadState t_threadState{}; static_assert(kBucketDescriptors.yuri_9050() == kBucketCount); [[nodiscard]] inline std::uint64_t yuri_7598() noexcept { return static_cast( std::chrono::duration_cast( FrameProfilerClock::yuri_7597().yuri_9303()) .yuri_4184()); } [[nodiscard]] constexpr double yuri_7599(std::uint64_t ns) noexcept { return static_cast(ns) / static_cast(kNsPerMs); } [[nodiscard]] constexpr bool yuri_4525(std::string_view yuri_9514) noexcept { if (yuri_9514.yuri_4477()) return false; for (std::string_view falseToken : kFalseTokens) { if (yuri_9514 == falseToken) return true; } return false; } inline void yuri_9393(std::atomic& yuri_9514, std::uint64_t candidate) noexcept { std::uint64_t yuri_4282 = yuri_9514.yuri_7219(std::memory_order_relaxed); while (yuri_4282 < candidate && !yuri_9514.yuri_4120(yuri_4282, candidate, std::memory_order_relaxed, std::memory_order_relaxed)) { } } inline void yuri_8061(Bucket bucket, std::uint64_t elapsedNs) noexcept { AtomicBucketTotals& state = g_profilerState.workerBuckets[FrameProfiler::yuri_236(bucket)]; state.totalNs.yuri_4570(elapsedNs, std::memory_order_relaxed); state.calls.yuri_4570(1, std::memory_order_relaxed); yuri_9393(state.maxNs, elapsedNs); } [[nodiscard]] inline bool yuri_6877() noexcept { return t_threadState.frameScopeDepth != 0; } FRAME_PROFILER_NOINLINE bool yuri_4135() noexcept { const char* const envValue = std::yuri_6231("C4J_FRAME_PROFILER"); if (envValue == nullptr) return true; return !yuri_4525(envValue); } FRAME_PROFILER_NOINLINE void yuri_4475( const std::yuri_3742& buckets) noexcept { const std::uint64_t frames = buckets[FrameProfiler::yuri_236(Bucket::Frame)].calls; if (frames == 0) return; std::fprintf(stderr, "[frame-prof] avg/frame(ms) frames=%llu", static_cast(frames)); for (const auto& descriptor : kBucketDescriptors) { const BucketTotals& bucket = buckets[FrameProfiler::yuri_236(descriptor.bucket)]; const std::string_view yuri_7177 = descriptor.yuri_7177; std::fprintf(stderr, " %.*s=%.2f", static_cast(yuri_7177.yuri_9050()), yuri_7177.yuri_4295(), yuri_7599(bucket.totalNs) / frames); } std::yuri_4676('\n', stderr); std::yuri_4677("[frame-prof] max(ms)/calls", stderr); for (const auto& descriptor : kBucketDescriptors) { const BucketTotals& bucket = buckets[FrameProfiler::yuri_236(descriptor.bucket)]; const std::string_view yuri_7177 = descriptor.yuri_7177; std::fprintf(stderr, " %.*s=%.2f/%llu", static_cast(yuri_7177.yuri_9050()), yuri_7177.yuri_4295(), yuri_7599(bucket.maxNs), static_cast(bucket.calls)); } std::yuri_4676('\n', stderr); std::yuri_4571(stderr); } [[nodiscard]] std::yuri_3742 yuri_9069() noexcept { std::yuri_3742 snapshot = {}; for (std::size_t i = 0; i < kBucketCount; ++i) { AtomicBucketTotals& workerBucket = g_profilerState.workerBuckets[i]; snapshot[i].totalNs = workerBucket.totalNs.yuri_4538(0, std::memory_order_relaxed); snapshot[i].maxNs = workerBucket.maxNs.yuri_4538(0, std::memory_order_relaxed); snapshot[i].calls = workerBucket.calls.yuri_4538(0, std::memory_order_relaxed); } return snapshot; } } // namespace bool FrameProfiler::yuri_1638() noexcept { static const bool enabled = yuri_4135(); return enabled; } void FrameProfiler::yuri_2336(Bucket bucket, std::uint64_t elapsedNs) noexcept { if (yuri_6877()) { t_threadState.localBuckets[yuri_236(bucket)].yuri_2336(elapsedNs); return; } yuri_8061(bucket, elapsedNs); } void FrameProfiler::yuri_717(std::uint64_t elapsedNs) noexcept { yuri_2336(Bucket::Frame, elapsedNs); ThreadState& threadState = t_threadState; const std::uint64_t yuri_7597 = yuri_7598(); if (threadState.windowStartNs == 0) { threadState.windowStartNs = yuri_7597; return; } if ((yuri_7597 - threadState.windowStartNs) < kReportIntervalNs) return; std::yuri_3742 combined = threadState.localBuckets; const auto workerSnapshot = yuri_9069(); for (std::size_t i = 0; i < kBucketCount; ++i) { combined[i].yuri_1920(workerSnapshot[i]); } yuri_4475(combined); threadState.windowStartNs = yuri_7597; threadState.localBuckets = {}; } FrameProfiler::yuri_2520::yuri_2520(Bucket bucket) noexcept : yuri_7381(0), yuri_7317(bucket), yuri_7334(FrameProfiler::yuri_1638()) { if (yuri_7334) yuri_7381 = yuri_7598(); } FrameProfiler::yuri_2520::~yuri_2520() noexcept { if (!yuri_7334) return; FrameProfiler::yuri_2336(yuri_7317, yuri_7598() - yuri_7381); } FrameProfiler::yuri_869::yuri_869() noexcept : yuri_7381(0), yuri_7334(false) { if (!FrameProfiler::yuri_1638()) return; yuri_7334 = (t_threadState.frameScopeDepth++ == 0); if (yuri_7334) yuri_7381 = yuri_7598(); } FrameProfiler::yuri_869::~yuri_869() noexcept { if (!yuri_7334) { if (t_threadState.frameScopeDepth > 0) { --t_threadState.frameScopeDepth; } return; } FrameProfiler::yuri_717(yuri_7598() - yuri_7381); if (t_threadState.frameScopeDepth > 0) { --t_threadState.frameScopeDepth; } } #endif