Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Precision time sleep using chrono

Tags:

c++

chrono

I want my application to sleep for precisely 2000 microseconds:

#include <iostream>
#include <chrono>
#include <thread>

std::cout << "Hello waiter" << std::endl;
std::chrono::microseconds dura( 2000 );

auto start = std::chrono::system_clock::now();
std::this_thread::sleep_for( dura );
auto end = std::chrono::system_clock::now();

auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "Waited for " << elapsed.count() << " microseconds" << std::endl;

This results in

Waited for 2620 microseconds

Where does this discrepancy come from? Is there a better (more precise) method available?

Thanks!

like image 927
user2926577 Avatar asked Feb 04 '15 00:02

user2926577


2 Answers

Quoted from cppreference (see sleep_for):

This function may block for longer than sleep_duration due to scheduling or resource contention delays.

I think that is the most likely explanation. The details will depend on your environment, especially your OS.

In general, I see no portable way to avoid it (non-portable options include increasing thread priorities or reducing the nice level).

Another, however less likely, reason for time differences are external clock adjustments (e.g., caused by a ntp daemon). Using a steady_clock is a portable insurance against clock adjustments.

like image 148
Philipp Claßen Avatar answered Nov 09 '22 20:11

Philipp Claßen


Evidently, sleep_for is not precise at all. The working solution for this issue is to enter a while loop until the desired duration is reached. This make the application "sleep" for precisely 2000 microseconds.

bool sleep = true;
while(sleep)
{
    auto now = std::chrono::system_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - start);
    if ( elapsed.count() > 2000 )
        sleep = false;
}
like image 2
user2926577 Avatar answered Nov 09 '22 21:11

user2926577