mirror of https://github.com/OpenTTD/OpenTTD
Codechange: TicToc can now accumulate and output every tick
parent
fca75fd06a
commit
4beb23af30
50
src/debug.h
50
src/debug.h
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue