I'm trying to limit the frames per second in a loop that is performing intersection checking, using C++ with chrono and thread.
Here is my code:
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::chrono::system_clock::time_point lastFrame = std::chrono::system_clock::now();
while (true)
{
// Maintain designated frequency of 5 Hz (200 ms per frame)
now = std::chrono::system_clock::now();
std::chrono::duration<double, std::milli> delta = now - lastFrame;
lastFrame = now;
if (delta.count() < 200.0)
{
std::chrono::duration<double, std::milli> delta_ms(200.0 - delta.count());
auto delta_ms_duration = std::chrono::duration_cast<std::chrono::milliseconds>(delta_ms);
std::this_thread::sleep_for(std::chrono::milliseconds(delta_ms_duration.count()));
}
printf("Time: %f \n", delta.count());
// Perform intersection test
}
The problem I'm having is that every other output of delta is showing miniscule amounts, rather than the ~200 ms / frame I'm aiming for:
Time: 199.253200
Time: 2.067700
Time: 199.420400
Time: 2.408100
Time: 199.494200
Time: 2.306200
Time: 199.586800
Time: 2.253400
Time: 199.864000
Time: 2.156500
Time: 199.293800
Time: 2.075500
Time: 201.787500
Time: 4.426600
Time: 197.304100
Time: 4.530500
Time: 198.457200
Time: 3.482000
Time: 198.365300
Time: 3.415400
Time: 198.467400
Time: 3.595000
Time: 199.730100
Time: 3.373400
Any thoughts as to why this is happening?
If you think about how your code works, you'll find out that it works exactly how you wrote it. Delta oscillates because of a logical mistake in the code.
This is what happens:
delta == 0
.200
, you code sleeps 200 - delta(0) == 200
ms.200
(because you've measured that sleep time as well as an actual work) and you sleep 200 - delta(200) == 0
ms.To fix the problem you need to not measure the sleep time.
This is how it can be done:
#include <iostream>
#include <cstdio>
#include <chrono>
#include <thread>
std::chrono::system_clock::time_point a = std::chrono::system_clock::now();
std::chrono::system_clock::time_point b = std::chrono::system_clock::now();
int main()
{
while (true)
{
// Maintain designated frequency of 5 Hz (200 ms per frame)
a = std::chrono::system_clock::now();
std::chrono::duration<double, std::milli> work_time = a - b;
if (work_time.count() < 200.0)
{
std::chrono::duration<double, std::milli> delta_ms(200.0 - work_time.count());
auto delta_ms_duration = std::chrono::duration_cast<std::chrono::milliseconds>(delta_ms);
std::this_thread::sleep_for(std::chrono::milliseconds(delta_ms_duration.count()));
}
b = std::chrono::system_clock::now();
std::chrono::duration<double, std::milli> sleep_time = b - a;
// Your code here
printf("Time: %f \n", (work_time + sleep_time).count());
}
}
This code gives me a steady sequence of deltas:
Time: 199.057206
Time: 199.053581
Time: 199.064718
Time: 199.053515
Time: 199.053307
Time: 199.053415
Time: 199.053164
Time: 199.053511
Time: 199.053280
Time: 199.053283