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
std::this_thread::yield
for this sort of thing? EDIT: i.e. is spinning while callingstd:this_thread::yield
an effective way of reducing the possibility of oversleeping – Nutbrown