Are longer sleeps (in C++) less precise than short ones

前端 未结 8 1086
情歌与酒
情歌与酒 2021-01-17 09:06

I have a task to do something every \"round\" minute(at xx:xx:00) And I use something like

const int statisticsInterval=60;
    time_t t=0;
    while (1)
            


        
相关标签:
8条回答
  • 2021-01-17 09:25

    Sleep works in terms of scheduler time quantums (Edit: Meanwhile, the majority of operating systems supports "tickless" schedulers, i.e. there are no longer fixed quantums, however, the principle remains true... there's timer coalescing and stuff).

    Unless you receive a signal there is no way you can wake up before that quantum has been used up. Also, sleep is not designed to be precise or accurate. Further, the time is more a guidline than a rule.

    While you may think of the sleep time in terms of "will continue after time X", that is not at all what's going on. Technically, sleep works in terms of "mark the thread not-ready for approximately time X, then mark it ready, invoke the scheduler, and then we'll see what happens". Note the subtle difference between being "ready" and actually running. A thread can in principle be ready for a very long time, and never run.
    Therefore, 60x sleep(1) can never be more accurate than sleep(60). It will make the thread not-ready and ready again 60 times, and it will invoke the scheduler 60 times. Since the scheduler cannot run in zero time (nor can a thread be made ready in zero time, nor can you do a context switch in zero time), sleeping many times for short durations necessarily needs to take longer than sleeping once for the cumulative time, in practice.

    Since you state that your OS is Ubuntu, you could as well use a timerfd[1]. Set the expire time to 1 minute and read() on it. If you get EINTR, just read() again. Otherwise, you know that a minute is up. Using a timer is the correct thing to do if you want precise timing (on a physical computer, it cannot be and will never be 100.00% perfect, but it will be as good as you can get, and it will avoid other systematic errors, especially with recurring events).
    The POSIX timer_create function will work as well, it's more portable, and it may be half a microsecond or so less overhead (maybe! maybe not!) but it is not nearly as comfortable and flexible as a timerfd.

    You cannot get more accurate and reliable than what a timer will provide. On my not particularly impressive Ubuntu machine, timerfds work accurately to a microsecond no problemo. As a plus, it's elegant too... if you ever need to do something else while waiting, such as listen on a socket, you can plug the timerfd into the same epoll as the socket descriptor. You can share it between several processes too, and wake them simultaneously. Or, or,... many other things.

    0 讨论(0)
  • 2021-01-17 09:31

    In general, Sleep is not the correct method for timing of anything. Better to use a precision timer with a callback function. On Windows, one may use the "Multimedia" timers, which have a resolution no greater than 1 ms on most hardware. see here. When the timer expires, the OS calls callback function in close to real time. see here.

    0 讨论(0)
  • 2021-01-17 09:37

    The answer is yes. It has nothing to do with C++ however. It has everything to do with the operating system.

    Because of the greater focus on low power use in current portable systems, the operating systems have been getting smarter about timers.

    Both Windows and Linux use timer slack in order to avoid waking up too often. This slack is automatically calculated using the timeout duration. It can be overridden in various ways if a really accurate timer is absolutely required.

    What this does for the operating system is to allow it to get into really deep sleep states. If timers are going off all of the time, the CPU and RAM don't get a chance to power down. But if timers are collected together into a batch, the CPU can power up, run all of the timer operations, then power down again.

    So if there are 10 programs all sleeping for 60 seconds but offset by a half-second or so, the most efficient use of the CPU is to wake up one time, run all 10 timers and then go back to sleep instead of waking up 10 times.

    0 讨论(0)
  • 2021-01-17 09:38

    sleep is not very precise in many cases. It depends on the OS how precise. In Windows 7, timer resolution is about 15,4 ms I think. Also, you can usually tell the scheduler how to handle sleep slacking...

    Here is a good read:

    Linux: http://linux.die.net/man/3/nanosleep

    Windows: http://msdn.microsoft.com/en-us/library/ms686298(v=vs.85).aspx

    PS: if you want higher precision on long waits, sleep some period and use the time diff based on a real-time clock. I.e. Store the current time when you start sleeping, then at each interval check how far you are from the set wait time.

    0 讨论(0)
  • 2021-01-17 09:39

    Boost.Thread implementation of sleep for POSIX systems can use different approaches to sleeping:

    1. Timed waiting on mutex in case when thread is created with Boost.Thread and has a specific thread information.
    2. Use pthread_delay_np, if available and thread is not created with Boost.Thread.
    3. USe nanosleep if pthread_delay_np is not available.
    4. Create a local mutex and do timed wait on it (worse case scenario if nothing else is available).

    Cases number 2, 3 and 4 are implemented in a loop of 5 times (as of Boost 1.44). So if sleeping thread is interrupted (i.e. with some signal) more than 5 times - there can be a potential problem. But that is not likely to happen.

    In all cases, precision will be much higher than a second, so doing multiple sleeps will not be more precise that doing a long one. You can only be concerned about your program being completely swapped out because of long sleep. For example, if machine is so busy, so kernel puts the whole program on disk. To avoid being swapped out, you have to spin (or do smaller sleeps and wake up occasionally). Usually, if performance matters a lot, programs do spin on a CPU and never call sleep, because any blocking call is to be avoided. But that is true if we are talking nano/micro-seconds.

    0 讨论(0)
  • 2021-01-17 09:45

    When you do sleep(N) it tells the OS to trigger the thread at current time + N.

    The reason why it isn't always accurate, is that you're not the only thread in the system.
    There might be another thread that asked to be waken at that time before you, and there might just be some important OS stuff that's needed to be performed exactly at that time.

    Anyway, there shouldn't be any precision issues, because the method has nothing to do with N.

    The only reason that it won't be "precise" is if it's a crappy OS that can't calculate the time right. And then again, the loop won't solve that.

    0 讨论(0)
提交回复
热议问题