Steady_Clock skipping between updates in main game loop

In the process of trying to work out a solid game loop in SFML I came across this issue which I can't seem to figure out. I was able to strip out all of the SFML code and still see the issue with clock() in time.h. Then I went further and still see the problem using std::chrono::steady_clock.

The issue: Somewhat consistently I see skips in the amount of work able to be done between updates. Each update should take 1/60th of a second, and the rest of the time is spend in Draw() getting as much drawing done as possible. Sometimes the amount of draws drops to 0 or 1 for no obvious reason. This bubbles up to the actual application in the form of noticeable stuttering. Other than the "skips" the number of draws done is very consistent.

Here is an image (notice the jump in update time and drop in draws): Console output of the issue

Some code:

#include <iostream>
#include <time.h>
#include <chrono>

using namespace std;
using namespace std::chrono;

void Draw()
{
    //for (int i = 0; i < 1000000; i++);
}

int main()
{
    steady_clock::time_point update_time;
    steady_clock::time_point update_next;
    int update_rate = 16666666; // 60 times a second (nanosecs)
    int updates;
    int max_updates = 5;
    int draws = 0;
    update_next = steady_clock::now();

    while (true)
    {
        updates = 0;
        update_time = steady_clock::now();
        while (duration_cast<nanoseconds>(update_time - update_next) > nanoseconds(update_rate) && updates++ < max_updates)
        {
            if (draws <= 1) {
                cout << "!!!!!!!!!!!!!ERROR!!!!!!!!!!!!!" << endl;
            }
            cout << "UPDATE - ";
            cout << "Draws: " << draws 
                 << " - UT - UN: " << duration_cast<nanoseconds>(update_time - update_next).count()
                 << endl;

            draws = 0;
            update_next += nanoseconds(update_rate);
        }
        draws++;
        Draw();
    }

    return 0;
}
  • Perhaps there is something I don't understand about typical applications? Does Windows need to hijack CPU cycles every so often?
  • I have seen this problem with steady_clock, clock, and in a fleshed out SFML app where work is done during Update and Draw
  • I assume SFML clock probably uses time.h clock
  • From my testing the max_updates checks have nothing to do with this issue (I don't think they are causing the problem)

The fact that I have seen this with a few different timers leads me to believe there is something wrong with my implementation or my system. This example was run in VS but I have seen it also in a standalone release exe. Playing with the update rate or the amount of work done in draw may help it show up for you.


After testing out my background processes I noticed a strange correlation. This skipping issue only occurs when the Spotify web player is open in chrome and occurs once a second or so.

I found this post which may be related: https://community.spotify.com/t5/Other-Partners-Web-Player-etc/Web-Player-on-Chrome-causes-lag-stutter/td-p/4587103

Perhaps there is something I don't understand about typical applications? Does Windows need to hijack CPU cycles every so often?

Yes, absolutely. Windows is running a whole lot of processes all at once. Now your application comes along and executes what is essentially a busy spin-loop. At some point, the OS is likely to de-prioritize this for longer than you expect because it just looks like a long calculation, and the OS needs to give other processes a fair share of CPU time.

In general you should not rely on your drawing routine being called an exact number of times per second, and your game's master clock should be able to cope with skipped frames. I'm not familiar with SFML so I can't comment on that.

However, I do have experience with realtime audio (and video for that matter) running in loops that exceed 1000 updates per second. You can improve your game loop time share by setting the thread priority to THREAD_PRIORITY_HIGHEST or THREAD_PRIORITY_TIME_CRITICAL (see SetThreadPriority).

For this to be effective you should also be a well-behaved application and periodically perform some kind of wait. Waiting allows the OS to do its necessary task-switching to service other processes (several of which will also be a high priority, and often higher than you will be able to force as a userspace application).

The obvious place for a wait is prior to your next draw cycle. Rather than spinning on your timer with 100% core utilization, simply calculate how long you're prepared to wait and call std::this_thread::sleep_for. Remember that the only guarantee is the sleep will be for at least the amount you specify. It absolutely can and will be more than this. But I recommend you start there and do some experiments.

Steady_Clock skipping between updates in main game loop, Steady_Clock skipping between updates in main game loop - c++. Then I went further and still see the problem using std::chrono::steady_clock. The issue:  Also note, that sometimes steady_clock is not steady, so include this so there are no surprises: static_assert( ClockType::is_steady, "Clock is not monotonically-increasing (steady)."); Note that Steady clock is not enabled by default on GCC4.7 (and others, I'm sure), but you can enable it with a flag.

In addition to @paddy's answer I recommend you look into fixed timesteps. If that isn't worth the trouble of implementing then you should also note that SFML has Window.setFramerateLimit(). It's not very precise but most simple games don't need significant precision.

Busy Loop/Spinning sometimes takes too long under Windows, Steady_Clock skipping between updates in main game loop. In the process of trying to work out a solid game loop in SFML I came across this issue which I can'​t  This is the other key job of a game loop: it runs the game at a consistent speed despite differences in the underlying hardware. The Pattern. A game loop runs continuously during gameplay. Each turn of the loop, it processes user input without blocking, updates the game state, and renders the game.

I've used spinning loop plus yield for 1 KHz control loops with good results, but expect some deadline miss (once in thousands cycles also long sleeping times).

Feedback on game loop using std::chrono : cpp_questions, Didn't even know steady_clock existed, thanks for the feedback! View entire discussion ( 8 comments). More posts from the cpp_questions community. The time points of this clock cannot decrease as physical time moves forward and the time between ticks of this clock is constant. This clock is not related to wall clock time (for example, it can be time since last reboot), and is most suitable for measuring intervals. std::chrono::steady_clock meets the requirements of TrivialClock.

It originally looked like the issue was caused by my antivirus, but I think I've actually narrowed it down to spotify web player being open and causing a performance spike 1/sec. I'm not sure why this would be.

Game Loop Timing : gamedev, I wrote an extremely simple frame limiting function for my game, but even For c​++11 you can use std::chrono::steady_clock, or boost::chrono::steady_clock if you​'re to force your game updates/physics to be a fixed number of ticks per second​, the The biggest problems arise with the Chinese commission, which decides​  So you want a loop that completes every 16.67 milliseconds. Usually it goes (simply put): Get input, do physics stuff, render, pause until 16.67ms has passed. Its usually done by saving the time at the top of the loop and then calculating the difference at the end and sleeping or looping doing nothing for that duration.

Update Method · Sequencing Patterns · Game Programming Patterns, The player's mighty valkyrie is on a quest to steal glorious jewels from where they rest Entity skeleton; bool patrollingLeft = false; double x = 0; // Main game loop: current object you're updating in the list, you can accidentally skip an object:. Objects of class steady_clock represent clocks for which values of time_point never decrease as physical time advances and for which values of time_point advance at a steady rate relative to real time. That is, the clock may not be adjusted.

Beginner C++ Game Programming Series, It also covers some basic graphics programming theory. you can use this page to jump through the lessons, skipping any B.S. you already know. Measuring time <chrono> std::chrono::steady_clock / duration; Assertions <assert.h> the last 5 or so years, and the reboot updates the tutorials to reflect those changes. What is the difference between steady_clock vs system_clock in layman terms. If you're holding a system_clock in your hand, you would call it a watch , and it would tell you what time it is. If you're holding a steady_clock in your hand, you would call it a stopwatch , and it would tell you how fast someone ran a lap, but it would not tell you what time it is.

How to fix this timestep once and for all?, One of the biggest reasons why I haven't released my game is because 1000; return ms; #else std::chrono::system_clock::time_point now One more thing to note here, my game has a badly written game loop. Methinks you need to decouple your graphics rendering from the rest of your game update. If you are cooking an egg, and need a timer that lasts 4 minutes, then you need it to last 4 minutes even if the current time is changed. If you've got a timer set for a meeting on the 5th at 3, then you absolutely need that timer to change if the local time changes. Hence the difference between steady_clock and system_clock here.

Comments
  • How effective is std::this_thread::yield for this sort of thing? EDIT: i.e. is spinning while calling std:this_thread::yield an effective way of reducing the possibility of oversleeping
  • I don't have personal experience using that for this kind of thing. I'd say it's more suited to things like spin-locks and very short-duration timing spins. I would definitely not want to run a 60Hz game loop with a spin-wait + yield, especially not if I'd also upped the thread priority.
  • Right, so as you edited your comment, then yes that could be a performance tweak. Since the sleep_for can come out late, you can use a shorter sleep than you need, then use yield for tighter spin "sleeps" that pad out any undershooting. That's down to experimentation and black magic.
  • I tried both of these, adding a thread sleep for as long as 10ms on each update, and still see the problem :(
  • The fixed timesteps link is a good one, and what I used to come up with the code example. I also see the issue even when using SFMLs setFrameLimit. For some reason the clock is jumping a huge amount of time.
  • Well the FrameLimit only keeps your loop from running too often on a fast cpu. It doesn't stop the framerate from dropping. What are you running in your background anyway? Could you try on a different machine?
  • Do you have the same issue if you use the Spotify desktop app instead? You could try doing performance profiling on your web browser to see what system calls might be responsible. Also try using the web app in different browsers, as it could be related to details in the browser implementation.