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

前端 未结 8 1149
情歌与酒
情歌与酒 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条回答
  •  旧时难觅i
    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.

提交回复
热议问题