CRM64Pro GDK v0.13.0
A free cross-platform game development kit built on top of SDL 3.0
Loading...
Searching...
No Matches

Description

Timer interface for timing control, frame rates and micro-benchmarking [v25.12.0].

Overview

The Timer interface manages all timing-related functionality including timer control, Render Frame Rate, Logic Frame Rate and micro-benchmarks. The Timer must be initiated with Timer::init().
One of the most important features is the fixed virtual logic frame rate with interpolation, which is implemented in this interface and in Main::update() method.

Key features

  • Timer control: Core timing management for application execution
  • Render Frame Rate (RFR): Asynchronous rendering rate control
  • Logic Frame Rate (LFR): Synchronous logic execution rate control
  • Micro-benchmarking: Statistical analysis of code snippet performance
  • Fixed virtual logic frame rate: Interpolation support for smooth gameplay

Frame rate types

By default, no preferred Render and Logic Frame Rate are set (both equal to 0). Use setRate() to configure specific values. Rates can be throttled down, but upper limits are imposed by the underlying hardware and ConfigMgr::iMTFriendly value.

Render Frame Rate (RFR)Asynchronous rate that does not stop your main loop. Renders all enabled and visible screens at the preferred rate. This rate is not guaranteed as some render frames may be dropped to maintain stable LFR. When vsync is enabled, set RFR to 0 for smoothest output
Logic Frame Rate (LFR)Synchronous rate that slows down your main loop to accommodate this rate. Under normal conditions (hardware can execute at preferred ratio), this rate remains quite stable

Micro-benchmarking system

The micro-benchmarking system measures small code snippets, capturing execution time and calculating statistical analysis on those measurements.



Thread safety
Although the system is not fully thread-safe, it can be made thread-safe by following these steps:

  1. Create micro-benchmarks on the same thread (usually main)
  2. Use each benchmark on different threads
  3. Close benchmarks from the same thread where they were created

Benchmark workflow

benchBegin()Create a named benchmark with estimated run count, or start a measurement cycle
benchEnd()End the current measurement cycle
benchStats()Retrieve statistical results into a Timer::Stats structure
benchClose()Close the benchmark and release resources

Usage examples

Deterministic function testing
Testing a function with a known number of iterations:

Main &mC64 = Main::Instance();
Timer::Stats myStats;
Sint32 iRuns = 1000;
Sint32 idBench = mC64.ITimer().benchBegin("myBench", iRuns);
for(Sint32 i = 0; i < iRuns; ++i)
{
mC64.ITimer().benchBegin(idBench);
func_to_be_tested();
mC64.ITimer().benchEnd(idBench);
}
mC64.ITimer().benchStats(idBench, myStats);
// Optionally call mC64.ITimer().info() to display stats via the default log
mC64.ITimer().benchClose(idBench);
static Main & Instance()
Access the Main singleton.
Definition CoreMain.cpp:361


Application behavior profiling
Measuring logic and render performance throughout application lifetime:

Main &mC64 = Main::Instance();
Timer::Stats myStats;
Sint32 iRuns = 10000; // Estimation; more will be allocated if needed
Sint32 idBenchL = mC64.ITimer().benchBegin("myBench-Logic", iRuns);
Sint32 idBenchR = mC64.ITimer().benchBegin("myBench-Render", iRuns);
while(iDone == 0)
{
// Logic stuff
mC64.ITimer().benchBegin(idBenchL);
...
mC64.ITimer().benchEnd(idBenchL);
// Render stuff
mC64.ITimer().benchBegin(idBenchR);
...
mC64.ITimer().benchEnd(idBenchR);
}
mC64.ITimer().info();
mC64.ITimer().benchClose(idBenchL);
mC64.ITimer().benchClose(idBenchR);

Best practices

  • Always call Timer::init() before using any timer functionality
  • Use setRate() to configure specific RFR and LFR values based on your application needs
  • Set RFR to 0 when vsync is enabled for the smoothest rendering output
  • Keep in mind that RFR applies to all enabled and visible screens
  • For micro-benchmarks, provide a reasonable estimation of run count to minimize reallocations
  • Create and close benchmarks on the same thread to ensure thread safety
  • Access the interface exclusively through Main::ITimer()
Note
The Timer interface is a singleton, automatically created once Main is instantiated. You can get a reference to this interface using Main::ITimer() method.
The Timer interface is automatically released when Main::Terminate() is called. At this time, any resource still loaded will be released, avoiding resource leaks.

Classes

class  CRM64Pro::Timer
 Timer class. More...

Enumerations

enum  CRM64Pro::eTimerState { CRM64Pro::TS_INIT = 0 , CRM64Pro::TS_RESET = 1 }
 Timer init state. More...

Functions

Sint32 CRM64Pro::Timer::info (Sint32 iMode=0)
 Request Timer Interface information.
Sint32 CRM64Pro::Timer::init (eTimerState tsOpt=TS_INIT)
 Initialize the timer system.
Sint32 CRM64Pro::Timer::setRate (Uint16 iR, Uint16 iL)
 Set preferred Render and Logic Frame Rate.
Sint32 CRM64Pro::Timer::getLFR ()
 Get the preferred Logic Frame Rate.
Sint32 CRM64Pro::Timer::getRFR ()
 Get the preferred Render Frame Rate.
float CRM64Pro::Timer::getAverageRFR ()
 Get the average Render Frame Rate since the last timer init or reset.
float CRM64Pro::Timer::getAverageLFR ()
 Get the average Logic Frame Rate since the last timer init or reset.
Uint32 CRM64Pro::Timer::getCurrentRFR ()
 Get current Render Frame Rate during last recent second.
Uint32 CRM64Pro::Timer::getCurrentLFR ()
 Get current Logic Frame Rate during last recent second.
Uint32 CRM64Pro::Timer::getRenderFrames ()
 Get total render frames since the last timer init or reset.
Uint32 CRM64Pro::Timer::getLogicFrames ()
 Get total logic frames since the last timer init or reset.
float CRM64Pro::Timer::getTime ()
 Get the execution time (in seconds) since the last timer init or reset.
Uint64 CRM64Pro::Timer::getTicks ()
 Get the execution time (in milliseconds) since the last timer init or reset.
Uint64 CRM64Pro::Timer::getTicksNow ()
 Get the execution time (in milliseconds) since the last timer init or reset.
Uint64 CRM64Pro::Timer::getHiResTime ()
 Get the execution time (in nanoseconds) since the last timer init or reset.
Sint32 CRM64Pro::Timer::benchBegin (const string &sName, Sint32 iRuns=0)
 Create and begin a microbenchmark test.
Sint32 CRM64Pro::Timer::benchBegin (Sint32 idBench)
 Begin a microbenchmark test.
Sint32 CRM64Pro::Timer::benchEnd (Sint32 idBench)
 End a microbenchmark test.
Sint32 CRM64Pro::Timer::benchClose (Sint32 idBench)
 Close a microbenchmark test.
Sint32 CRM64Pro::Timer::benchStats (Sint32 idBench, Stats &stats)
 Calculate the statistical analysis given the current measurements.

Enumeration Type Documentation

◆ eTimerState

Timer init state.

Enumerator
TS_INIT 

'tsOpt' parameter in Timer::init(), initializes or resets all timer settings.

TS_RESET 

'tsOpt' parameter in Timer::init(), only resets the timer if it was previously initialized keeping RFR and LFR rates.

Function Documentation

◆ info()

Sint32 CRM64Pro::Timer::info ( Sint32 iMode = 0)

Request Timer Interface information.

Writes information to the default log.

Parameters
iMode-1 for displaying only Manager information. 0 (default) for displaying Manager and all Objects information.
Returns
0 on success, or a negative error code on failure.

◆ init()

Sint32 CRM64Pro::Timer::init ( eTimerState tsOpt = TS_INIT)

Initialize the timer system.

The first call to this method initializes the SDL timer subsystem.

Parameters
tsOptCheck ::eTimerState enum for further information. Default is TS_INIT.
Returns
0 on success, or a negative error code on failure.
Note
init(TS_RESET) is called internally by Main::cleanUp().

◆ setRate()

Sint32 CRM64Pro::Timer::setRate ( Uint16 iR,
Uint16 iL )

Set preferred Render and Logic Frame Rate.

Parameters
iRpreferred Render Frame Rate. Default 0 means unlimited. Maximum value is 500.
iLpreferred Logic Frame Rate. Default 0 means unlimited. Maximum value is 20000.
Returns
0 on success, or a negative error code on failure.

◆ getLFR()

Sint32 CRM64Pro::Timer::getLFR ( )

Get the preferred Logic Frame Rate.

Returns
0 or positive value on success or -1 on failure.

◆ getRFR()

Sint32 CRM64Pro::Timer::getRFR ( )

Get the preferred Render Frame Rate.

Returns
0 or positive value on success or -1 on failure.

◆ getAverageRFR()

float CRM64Pro::Timer::getAverageRFR ( )

Get the average Render Frame Rate since the last timer init or reset.

Returns
0 or positive value on success or -1 on failure.

◆ getAverageLFR()

float CRM64Pro::Timer::getAverageLFR ( )

Get the average Logic Frame Rate since the last timer init or reset.

Returns
0 or positive value on success or -1 on failure.

◆ getCurrentRFR()

Uint32 CRM64Pro::Timer::getCurrentRFR ( )

Get current Render Frame Rate during last recent second.

Returns
Render Frame Rate.

◆ getCurrentLFR()

Uint32 CRM64Pro::Timer::getCurrentLFR ( )

Get current Logic Frame Rate during last recent second.

Returns
Logic Frame Rate.

◆ getRenderFrames()

Uint32 CRM64Pro::Timer::getRenderFrames ( )

Get total render frames since the last timer init or reset.

Returns
Total number of Render frames.

◆ getLogicFrames()

Uint32 CRM64Pro::Timer::getLogicFrames ( )

Get total logic frames since the last timer init or reset.

Returns
Total number of Logic frames.

◆ getTime()

float CRM64Pro::Timer::getTime ( )

Get the execution time (in seconds) since the last timer init or reset.

This time will be constant inside the same Logic Frame iteration and will be updated on Main::update() if a new Logic Frame must be produced.

Returns
0 or positive value on success or -1 on failure.

◆ getTicks()

Uint64 CRM64Pro::Timer::getTicks ( )

Get the execution time (in milliseconds) since the last timer init or reset.

This time will be constant inside the same Logic Frame iteration and will be updated on Main::update() if a new Logic Frame must be produced.

Returns
unsigned int 32bits with the milliseconds.

◆ getTicksNow()

Uint64 CRM64Pro::Timer::getTicksNow ( )

Get the execution time (in milliseconds) since the last timer init or reset.

This time will be exactly the "now" time, on other words, it is not linked anyway to the Logic Frame iteration.

Returns
unsigned int 32bits with the milliseconds.

◆ getHiResTime()

Uint64 CRM64Pro::Timer::getHiResTime ( )

Get the execution time (in nanoseconds) since the last timer init or reset.

This is the high resolution timer when you need more accurate time precision.

Returns
unsigned 64bits with the nanoseconds.

◆ benchBegin() [1/2]

Sint32 CRM64Pro::Timer::benchBegin ( const string & sName,
Sint32 iRuns = 0 )

Create and begin a microbenchmark test.

Parameters
sNamestring with the name of this benchmark.
iRunsestimated number of runs. Default 0 (automatically managed).
Returns
greater than 0 on success (the Bench id) or a negative error code on failure.
Note
If the benchmark already exists, it just begins the benchmark. Use benchBegin() with Bench id for better performance. Each benchBegin() must be followed by a benchEnd().

◆ benchBegin() [2/2]

Sint32 CRM64Pro::Timer::benchBegin ( Sint32 idBench)

Begin a microbenchmark test.

Parameters
idBenchBench id.
Returns
0 on success, or a negative error code on failure.
Note
Each benchBegin() must be followed by a benchEnd().

◆ benchEnd()

Sint32 CRM64Pro::Timer::benchEnd ( Sint32 idBench)

End a microbenchmark test.

Parameters
idBenchBench id.
Returns
0 on success, or a negative error code on failure.
Note
Each benchBegin() must be followed by a benchEnd().

◆ benchClose()

Sint32 CRM64Pro::Timer::benchClose ( Sint32 idBench)

Close a microbenchmark test.

Free the resources of the test and the stats.

Parameters
idBenchBench id.
Returns
0 on success, or a negative error code on failure.

◆ benchStats()

Sint32 CRM64Pro::Timer::benchStats ( Sint32 idBench,
Stats & stats )

Calculate the statistical analysis given the current measurements.

Parameters
idBenchBench id.
statsa Stats struct to be filled with current stats. The values are given in milliseconds.
Returns
0 on success, or a negative error code on failure.