1
0
Fork 0

Codechange: TicToc can now accumulate and output every tick

pull/14323/head
glx22 2025-05-22 21:55:31 +02:00 committed by Loïc Guilloux
parent fca75fd06a
commit 4beb23af30
2 changed files with 48 additions and 7 deletions

View File

@ -61,20 +61,49 @@ void SetDebugString(std::string_view s, SetDebugStringErrorFunc error_func);
std::string GetDebugString(); std::string GetDebugString();
/** TicToc profiling. /** TicToc profiling.
* Usage: * Usage for max_count based output:
* static TicToc::State state("A name", 1); * static TicToc::State state("A name", 1);
* TicToc tt(state); * TicToc tt(state);
* --Do your code-- * --Do your code--
*
* Usage for per-tick output:
* static TicToc::State state("A name");
* TicToc tt(state);
* --Do your code--
*/ */
struct TicToc { struct TicToc {
/** Persistent state for TicToc profiling. */ /** Persistent state for TicToc profiling. */
struct State { struct State {
const std::string_view name; const std::string_view name;
const uint32_t max_count; const std::optional<uint32_t> max_count;
uint32_t count = 0; uint32_t count = 0;
uint64_t chrono_sum = 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 *>;
State(std::string_view name, std::optional<uint32_t> 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<double>(this->count));
this->count = 0;
this->chrono_sum = 0;
}
}; };
State &state; State &state;
@ -85,10 +114,17 @@ struct TicToc {
inline ~TicToc() inline ~TicToc()
{ {
this->state.chrono_sum += (std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - this->chrono_start)).count(); this->state.chrono_sum += (std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - this->chrono_start)).count();
if (++this->state.count == this->state.max_count) { this->state.count++;
Debug(misc, 0, "[{}] {} us [avg: {:.1f} us]", this->state.name, this->state.chrono_sum, this->state.chrono_sum / static_cast<double>(this->state.count)); if (this->state.max_count.has_value() && this->state.count == this->state.max_count.value()) {
this->state.count = 0; this->state.OutputAndReset("MaxCount");
this->state.chrono_sum = 0; }
}
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);
} }
} }
}; };

View File

@ -10,6 +10,7 @@
#ifndef VIDEO_VIDEO_DRIVER_HPP #ifndef VIDEO_VIDEO_DRIVER_HPP
#define VIDEO_VIDEO_DRIVER_HPP #define VIDEO_VIDEO_DRIVER_HPP
#include "../debug.h"
#include "../driver.h" #include "../driver.h"
#include "../core/geometry_type.hpp" #include "../core/geometry_type.hpp"
#include "../core/math_func.hpp" #include "../core/math_func.hpp"
@ -318,6 +319,8 @@ protected:
if (_ddc_fastforward) return std::chrono::microseconds(0); if (_ddc_fastforward) return std::chrono::microseconds(0);
#endif /* DEBUG_DUMP_COMMANDS */ #endif /* DEBUG_DUMP_COMMANDS */
TicToc::Tick("GameTick");
/* If we are paused, run on normal speed. */ /* If we are paused, run on normal speed. */
if (_pause_mode.Any()) return std::chrono::milliseconds(MILLISECONDS_PER_TICK); if (_pause_mode.Any()) return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
/* Infinite speed, as quickly as you can. */ /* Infinite speed, as quickly as you can. */
@ -328,6 +331,8 @@ protected:
std::chrono::steady_clock::duration GetDrawInterval() std::chrono::steady_clock::duration GetDrawInterval()
{ {
TicToc::Tick("DrawTick");
/* If vsync, draw interval is decided by the display driver */ /* If vsync, draw interval is decided by the display driver */
if (_video_vsync && this->uses_hardware_acceleration) return std::chrono::microseconds(0); if (_video_vsync && this->uses_hardware_acceleration) return std::chrono::microseconds(0);
return std::chrono::microseconds(1000000 / _settings_client.gui.refresh_rate); return std::chrono::microseconds(1000000 / _settings_client.gui.refresh_rate);