skip to Main Content

I call this function in my centos 7 server.

I find std::this_thread::sleep_for(chrono::nanoseconds(1)) actually sleep for one ms, Is there any explanation? I think it may be caused by os setting?

3

Answers


  1. From sleep_for documentation, you can see that:

    Blocks the execution of the current thread for at least the specified sleep_duration.

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

    The most likely cause is that your process scheduler kicks out the sleeping thread and doesn’t reschedule it for a millisecond.

    Login or Signup to reply.
  2. Let’s first check what guarantees the specification gives you (quotes from the latest daft of the C++ standard):

    [thread.req.timing]

    Implementations necessarily have some delay in returning from a timeout.
    Any overhead in interrupt response, function return, and scheduling induces a “quality of implementation” delay, expressed as duration Di.
    Ideally, this delay would be zero.
    Further, any contention for processor and memory resources induces a “quality of management” delay, expressed as duration Dm.
    The delay durations may vary from timeout to timeout, but in all cases shorter is better.

    The functions whose names end in _­for take an argument that specifies a duration. … Given a duration argument Dt, the real-time duration of the timeout is Dt+Di+Dm.

    The resolution of timing provided by an implementation depends on both operating system and hardware. …

    So, it is expected for the slept time to be longer than Dt given as the argument.

    Assuming your test was correct, we can use it to calculate that Di+Dm was about a millisecond on your system with your hardware in that particular execution.

    Is there any simple method can ensure i sleep for 1us?

    No, not in standard C++ for on all systems.

    It may potentially be possible on a real-time capable system. See the documentation of the system that you are targeting.

    Login or Signup to reply.
  3. You’ve got the question you asked covered by the other answers, but you also asked a question in the comments:

    Is there any simple method can ensure i sleep for 1us?

    Instead of calling sleep_for, yielding the thread’s execution slot, you could busy-sleep. That is, loop until a certain amount of time has passed. It’ll often get more accurate results at the cost of making that CPU thread unusable for doing anything else.

    Here’s one example with a function called busy_sleep():

    // get a rough estimate of how much overhead there is in calling buzy_sleep()
    std::chrono::nanoseconds calc_overhead() {
        using namespace std::chrono;
        constexpr size_t tests = 1001;
        constexpr auto timer = 200us;
    
        auto init = [&timer]() {
            auto end = steady_clock::now() + timer;
            while(steady_clock::now() < end);
        };
    
        time_point<steady_clock> start;
        nanoseconds dur[tests];
    
        for(auto& d : dur) {
            start = steady_clock::now();
            init();
            d = steady_clock::now() - start - timer;
        }
        std::sort(std::begin(dur), std::end(dur));
        // get the median value or something a little less as in this example:
        return dur[tests / 3];
    }
    
    // initialize the overhead constant that will be used in busy_sleep()
    static const std::chrono::nanoseconds overhead = calc_overhead();
    
    inline void busy_sleep(std::chrono::nanoseconds t) {
        auto end = std::chrono::steady_clock::now() + t - overhead;
        while(std::chrono::steady_clock::now() < end);
    }
    

    Demo

    Note: This was updated after it was accepted since I noticed that the overhead calculation could sometimes get terribly wrong. The updated example should be less fragile.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search