From 4beb23af3079e641e54c9298e69ead5d5134cbc5 Mon Sep 17 00:00:00 2001 From: glx22 Date: Thu, 22 May 2025 21:55:31 +0200 Subject: [PATCH] Codechange: TicToc can now accumulate and output every tick --- src/debug.h | 50 ++++++++++++++++++++++++++++++++------ src/video/video_driver.hpp | 5 ++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/debug.h b/src/debug.h index ce02e16ff0..161d4a3922 100644 --- a/src/debug.h +++ b/src/debug.h @@ -61,20 +61,49 @@ void SetDebugString(std::string_view s, SetDebugStringErrorFunc error_func); std::string GetDebugString(); /** TicToc profiling. - * Usage: + * Usage for max_count based output: * static TicToc::State state("A name", 1); * TicToc tt(state); * --Do your code-- + * + * Usage for per-tick output: + * static TicToc::State state("A name"); + * TicToc tt(state); + * --Do your code-- */ struct TicToc { /** Persistent state for TicToc profiling. */ struct State { const std::string_view name; - const uint32_t max_count; + const std::optional max_count; uint32_t count = 0; uint64_t chrono_sum = 0; - constexpr State(std::string_view name, uint32_t max_count) : name(name), max_count(max_count) { } + using States = std::vector; + + State(std::string_view name, std::optional max_count = {}) : name(name), max_count(max_count) + { + GetStates().push_back(this); + } + + ~State() + { + /* Container might be already destroyed. */ + if (!GetStates().empty()) std::erase(GetStates(), this); + } + + static States &GetStates() + { + thread_local static States s_states; + return s_states; + } + + void OutputAndReset(const std::string_view prefix = "") + { + Debug(misc, 0, "[{}] [{}] {} calls in {} us [avg: {:.1f} us]", prefix, this->name, this->count, this->chrono_sum, this->chrono_sum / static_cast(this->count)); + this->count = 0; + this->chrono_sum = 0; + } }; State &state; @@ -85,10 +114,17 @@ struct TicToc { inline ~TicToc() { this->state.chrono_sum += (std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - this->chrono_start)).count(); - if (++this->state.count == this->state.max_count) { - Debug(misc, 0, "[{}] {} us [avg: {:.1f} us]", this->state.name, this->state.chrono_sum, this->state.chrono_sum / static_cast(this->state.count)); - this->state.count = 0; - this->state.chrono_sum = 0; + this->state.count++; + if (this->state.max_count.has_value() && this->state.count == this->state.max_count.value()) { + this->state.OutputAndReset("MaxCount"); + } + } + + static void Tick(const std::string_view prefix) + { + for (auto state : State::GetStates()) { + if (state->max_count.has_value() || state->count == 0) continue; + state->OutputAndReset(prefix); } } }; diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp index d79d4c393c..c6229da341 100644 --- a/src/video/video_driver.hpp +++ b/src/video/video_driver.hpp @@ -10,6 +10,7 @@ #ifndef VIDEO_VIDEO_DRIVER_HPP #define VIDEO_VIDEO_DRIVER_HPP +#include "../debug.h" #include "../driver.h" #include "../core/geometry_type.hpp" #include "../core/math_func.hpp" @@ -318,6 +319,8 @@ protected: if (_ddc_fastforward) return std::chrono::microseconds(0); #endif /* DEBUG_DUMP_COMMANDS */ + TicToc::Tick("GameTick"); + /* If we are paused, run on normal speed. */ if (_pause_mode.Any()) return std::chrono::milliseconds(MILLISECONDS_PER_TICK); /* Infinite speed, as quickly as you can. */ @@ -328,6 +331,8 @@ protected: std::chrono::steady_clock::duration GetDrawInterval() { + TicToc::Tick("DrawTick"); + /* If vsync, draw interval is decided by the display driver */ if (_video_vsync && this->uses_hardware_acceleration) return std::chrono::microseconds(0); return std::chrono::microseconds(1000000 / _settings_client.gui.refresh_rate);