🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Default timing method in real time apps

Started by
8 comments, last by Calin 4 years, 3 months ago

What`s the default timing method in real time apps (games)? The Microsoft samples I use call timeGetTime() , In my other projects I had QueryPerformanceCounter for timing. @Juliean or anyone else

My project`s facebook page is “DreamLand Page”

Advertisement

Well, post C++11 I used QueryPerformanceCounter (wrapped in a timer-class). timeGetTime() is a little less accurate.

Now the modern variant (hey, you asked for it) which is portable is std::chrono::high_performance_clock. Thats how my timer internally looks now:

#pragma once
#include <chrono>

namespace ae::core
{

	class Timer
	{
	public:
		Timer(void);

		void Reset(void);
		double Duration(void) const;

	private:
		std::chrono::high_resolution_clock::time_point m_start;
	};
}

// .cpp

#include "Timer.h"

namespace ae::core
{

	[[nodiscard]] inline auto getNow(void) noexcept
	{
		return std::chrono::high_resolution_clock::now();
	}

	Timer::Timer(void) : 
		m_start(getNow()) {}

	void Timer::Reset(void)
	{
		m_start = getNow();
	}

	double Timer::Duration(void) const
	{
		const auto end = getNow();
		const std::chrono::duration<double> duration = end - m_start;

		return duration.count();
	}

}

Juliean said:
Now the modern variant (hey, you asked for it) which is portable is std::chrono::high_performance_clock. Thats how my timer internally looks now:

Did you compare accuracy against QueryPerformanceCounter()?

I'm still using the old school way, which is ugly and works only for Windows:

#include <stdint.h>
#include <windows.h>
#include <Mmsystem.h>


uint64_t SystemTools::GetTimeNS ()
 // returns nano seconds
{
	static LARGE_INTEGER ticksPerSec;
	static bool initialized = false;

	if (!initialized) 
	{
		QueryPerformanceFrequency(&ticksPerSec); 
		initialized = true;
	}
	LARGE_INTEGER now;
	QueryPerformanceCounter(&now);
	return (uint64_t) ((1e9 * now.QuadPart) / ticksPerSec.QuadPart);
}

This could be improved by updating the frequency more often than just once. But that's expensive and even more ugly. So i would recommend the modern version above.

timeGetTime() is very inaccurate - not useful for games in practice.

JoeJ said:
Did you compare accuracy against QueryPerformanceCounter()?

Well, I can tell you what the windows header says:

 struct steady_clock { // wraps QueryPerformanceCounter
        using rep                       = long long;
        using period                    = nano;
        using duration                  = nanoseconds;
        using time_point                = chrono::time_point<steady_clock>;
        static constexpr bool is_steady = true;

        _NODISCARD static time_point now() noexcept { // get current time
            const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot
            const long long _Ctr  = _Query_perf_counter();
            static_assert(period::num == 1, "This assumes period::num == 1.");
            const long long _Whole = (_Ctr / _Freq) * period::den;
            const long long _Part  = (_Ctr % _Freq) * period::den / _Freq;
            return time_point(duration(_Whole + _Part));
        }
    };

    using high_resolution_clock = steady_clock;

high_resolution_clock even says in the documentation that it mostly just uses std::steady_clock, but that seems to be a wrapper for QueryPerformanceCounter. So should be safe to upgrade :P

EDIT: Also its interesting to see that the windows function doesn't cache the frequency in a static. Though I think I have to agree with them here, the cost of having those two additional threat-safe static variables + branch probably outweights calling the function every time.

Thanks I will come with a followup

My project`s facebook page is “DreamLand Page”

Just as a data point, I provide library implementations for a safety-certified hard realtime operating system. Requirements ore stricter than for games. Most of the customers I deal with do pretty much exactly as @juliean describes: std::chrono::highresolutionclock in C++ and an OS-specific kernel call to get a monotonic high-resolution timer (not a clock, but for example Microsoft Window's Query_perfcounter()) from C. Note that the C++ high resolution clock simply wraps the OSspecific high-resolution timer on many platforms (Windows, Mac OS) but not, as far as I know, on Linux where the popular standard library implementations simply wrap the POSIX systemclock().

Stephen M. Webb
Professional Free Software Developer

my humble app/game isn`t that demanding in terms of precision, made my pick, thanks for sharing.

My project`s facebook page is “DreamLand Page”

Calin said:

What`s the default timing method in real time apps (games)?

In most games, systems run as fast as possible.

Games rarely sleep, and they don't probe the clock for how long they can rest. They run tasks until they are blocked, waiting for the hardware to do something, then they continue running as fast as they can.

Typically the display loop is tied to the simulation. The loop is to check the current time versus the time of the last simulation, run the simulator zero or more times to catch it up, then display an image. Displaying the image is a blocking operation, so the simulation waits until the display is complete, then repeates.

Often there are other tasks going on. Networking waits until network data is available, process it, then goes back to sleep waiting for more data. Asynchronous disk queues are similar, waiting for pending disk data, processing the loaded data when it gets in, then back to waiting. Audio processing is often asynchronous, updating circular audio buffers as quickly as they're able to play. In some games input like mouse clicks and keyboard input are handled asynchronously.

frob said:
run the simulator … to catch it up

I`m making the connection.

My project`s facebook page is “DreamLand Page”

This topic is closed to new replies.

Advertisement