The following code utilizes C++11 std::chrono
to accumulate delta time between two subsequent ticks, and outputs the number of ticks accumulated for each second interval and the average tick time over this 1 second interval.
However, under my Xcode environment, when I run the code (in Debug), the outputs seem to be much longer than 1 second apart (likely at least 2 seconds apart) - it seems that the time line is extended longer than the actual time line.
If uncommenting the sleep line, the code exhibits the correct behavior.
Can anyone tell me what's going wrong?
#include <iostream>
#include <chrono>
#include <thread>
std::chrono::high_resolution_clock::time_point then{};
double accumulator = 0.0;
size_t count = 0;
void Tick()
{
if (then != std::chrono::high_resolution_clock::time_point{}) {
auto delta = std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - then).count();
accumulator += delta;
++count;
if (accumulator >= 1.0) {
std::cout << "count: " << count << " | average delta: " << 1.0 / count << std::endl;
accumulator = 0.0;
count = 0;
}
} else {
std::cout << "###" << std::endl;
}
then = std::chrono::high_resolution_clock::now();
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
while (true) {
Tick();
// uncomment the following line exhibits the correct behavior
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return 0;
}
So, after some digging, it is revealed that the delta
computation logic together with how now
is used are flawed. Several points:
now
should only be recorded once entering the Tick
function and used across the entire scopedelta
, that's why the accumulation of the partial delta
's is less than the actual time elapsed, thus it appeared that the time is extended more than the actual time line!The working code looks like below:
#include <iostream>
#include <chrono>
#include <thread>
std::chrono::high_resolution_clock::time_point then{};
double accumulator = 0.0;
size_t count = 0;
void Tick()
{
auto now = std::chrono::high_resolution_clock::now(); // the time point of this tick
if (then != std::chrono::high_resolution_clock::time_point{}) {
auto delta = std::chrono::duration<double>(now - then).count(); // should use the recorded time point 'now'
accumulator += delta;
++count;
if (accumulator >= 1.0) {
std::cout << "count: " << count << " | average delta: " << 1.0 / count << std::endl;
accumulator = 0.0;
count = 0;
}
} else {
std::cout << "###" << std::endl;
}
then = now; // should use the recorded time point as this tick time
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
while (true) {
Tick();
// other processing
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return 0;
}