17#include "3rdparty/fmt/chrono.h"
25std::vector<NewGRFProfiler> _newgrf_profilers;
50 using namespace std::chrono;
53 this->
cur_call.
time = (uint32_t)time_point_cast<microseconds>(high_resolution_clock::now()).time_since_epoch().count();
65 using namespace std::chrono;
66 this->
cur_call.
time = (uint32_t)time_point_cast<microseconds>(high_resolution_clock::now()).time_since_epoch().count() - this->
cur_call.
time;
69 uint32_t operator()(std::monostate)
73 uint32_t operator()(CallbackResult cb_result)
79 if (group ==
nullptr)
return 0;
80 if (group->type != SGT_RESULT)
return group->nfo_line;
97void NewGRFProfiler::Start()
104uint32_t NewGRFProfiler::Finish()
106 if (!this->
active)
return 0;
108 if (this->
calls.empty()) {
109 IConsolePrint(
CC_DEBUG,
"Finished profile of NewGRF [{:08X}], no events collected, not writing a file.", std::byteswap(this->
grffile->grfid));
116 IConsolePrint(
CC_DEBUG,
"Finished profile of NewGRF [{:08X}], writing {} events to '{}'.", std::byteswap(this->
grffile->grfid), this->calls.size(), filename);
118 uint32_t total_microseconds = 0;
122 if (!f.has_value()) {
125 fmt::print(*f,
"Tick,Sprite,Feature,Item,CallbackID,Microseconds,Depth,Result\n");
126 for (
const Call &c : this->
calls) {
127 fmt::print(*f,
"{},{},0x{:X},{},0x{:X},{},{},{}\n", c.tick, c.root_sprite, c.feat, c.item, (uint)c.cb, c.time, c.subs, c.result);
128 total_microseconds += c.time;
133 return total_microseconds;
136void NewGRFProfiler::Abort()
148 return fmt::format(
"{}grfprofile-{:%Y%m%d-%H%M}-{:08X}.csv",
FiosGetScreenshotDir(), fmt::localtime(time(
nullptr)), std::byteswap(this->
grffile->grfid));
151 uint32_t NewGRFProfiler::FinishAll()
155 uint64_t max_ticks = 0;
156 uint32_t total_microseconds = 0;
159 total_microseconds += pr.Finish();
164 if (total_microseconds > 0 && max_ticks > 0) {
165 IConsolePrint(
CC_DEBUG,
"Total NewGRF callback processing: {} microseconds over {} ticks.", total_microseconds, max_ticks);
168 return total_microseconds;
176 NewGRFProfiler::FinishAll();
A timeout timer will fire once after the interval.
void Reset()
Reset the timer, so it will fire again after the timeout.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
@ NONE
These timers can be executed in any order; the order is not relevant.
void IConsolePrint(TextColour colour_code, const std::string &string)
Handle the printing of text entered into the console or redirected there by any other means.
Console functions used outside of the console code.
static const TextColour CC_DEBUG
Colour for debug output.
static const TextColour CC_ERROR
Colour for error lines.
std::optional< FileHandle > FioFOpenFile(std::string_view filename, std::string_view mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Functions for Standard In/Out file operations.
std::string_view FiosGetScreenshotDir()
Get the directory for screenshots.
@ NO_DIRECTORY
A path without any base directory.
static TimeoutTimer< TimerGameTick > _profiling_finish_timeout({ TimerGameTick::Priority::NONE, 0 }, []() { NewGRFProfiler::FinishAll();})
Check whether profiling is active and should be finished.
Profiling of NewGRF action 2 handling.
std::variant< std::monostate, CallbackResult, const SpriteGroup * > ResolverResult
Result of resolving sprite groups:
A number of safeguards to prevent using unsafe methods.
uint32_t GetSpriteLocalID(SpriteID sprite)
Get the GRF-local sprite id of a given sprite.
Functions to cache sprites in memory.
Definition of base types and functions in a cross-platform compatible way.
Functions related to low-level strings.
Dynamic data of a loaded NewGRF.
GrfSpecFeature feat
GRF feature being resolved for.
uint32_t time
Time taken for resolution (microseconds)
uint32_t subs
Sub-calls to other sprite groups.
uint32_t root_sprite
Pseudo-sprite index in GRF file.
CallbackID cb
Callback ID.
uint32_t item
Local ID of item being resolved for.
uint32_t result
Result of callback.
Callback profiler for NewGRF development.
void RecursiveResolve()
Capture a recursive sprite group resolution.
static void StartTimer(uint64_t ticks)
Start the timeout timer that will finish all profiling sessions.
void EndResolve(const ResolverResult &result)
Capture the completion of a sprite group resolution.
~NewGRFProfiler()
Complete profiling session and write data to file.
Call cur_call
Data for current call in progress.
bool active
Is this profiler collecting data.
const GRFFile * grffile
Which GRF is being profiled.
uint64_t start_tick
Tick number this profiler was started on.
static void AbortTimer()
Abort the timeout timer, so the timer callback is never called.
void BeginResolve(const ResolverObject &resolver)
Capture the start of a sprite group resolution.
NewGRFProfiler(const GRFFile *grffile)
Create profiler object and begin profiling session.
std::vector< Call > calls
All calls collected so far.
std::string GetOutputFilename() const
Get name of the file that will be written.
Interface for SpriteGroup-s to access the gamestate.
virtual uint32_t GetDebugID() const
Get an identifier for the item being resolved.
CallbackID callback
Callback being resolved.
virtual GrfSpecFeature GetFeature() const
Get the feature number being resolved for.
const SpriteGroup * root_spritegroup
Root SpriteGroup to use for resolving.
Definition of Interval and OneShot timers.
Definition of the tick-based game-timer.