epoll_wait(5, {}, 1024, 99) = 0 <0.099287> <= First epoll() wait 99.287ms
sync() = 0 <0.054469>
epoll_wait(5, {}, 1024, 100) = 0 <0.100211> <= Second epoll() wait 100.211ms
sync() = 0 <0.040866>
epoll_wait(5, {}, 1024, 100) = 0 <0.100207> <===
sync() = 0 <0.046870>
epoll_wait(5, {}, 1024, 100) = 0 <0.100214> <===
sync() = 0 <0.043035>
epoll_wait(5, {}, 1024, 100) = 0 <0.100139> <===
00:31:27.960802 sync() = 0
00:31:28.106703 sync() = 0
00:31:28.250530 sync() = 0
00:31:28.391060 sync() = 0
00:31:28.529861 sync() = 0
00:31:28.669751 sync() = 0
00:31:28.810477 sync() = 0
00:31:28.949302 sync() = 0
timerfd_create(CLOCK_MONOTONIC, 0) = 9 <0.000013>
timerfd_settime(9, 0, {it_interval={0, 100000000}, it_value={0, 100000000}}, NULL) = 0 <0.000014>
read(9, "\1\0\0\0\0\0\0\0", 8) = 8 <0.100138> <== First read() on timerd fd file wait 100.138ms
sync() = 0 <0.053847>
read(9, "\1\0\0\0\0\0\0\0", 8) = 8 <0.045944> <= Second read() wait 45.944ms
sync() = 0 <0.047778>
read(9, "\1\0\0\0\0\0\0\0", 8) = 8 <0.051987> <===
sync() = 0 <0.046731>
read(9, "\1\0\0\0\0\0\0\0", 8) = 8 <0.053102> <===
sync() = 0 <0.044829>
read(9, "\1\0\0\0\0\0\0\0", 8) = 8 <0.055018> <===
00:47:23.687205 sync() = 0
00:47:23.787220 sync() = 0
00:47:23.887393 sync() = 0
00:47:23.987276 sync() = 0
00:47:24.087210 sync() = 0
00:47:24.187164 sync() = 0
00:47:24.287242 sync() = 0
00:47:24.387330 sync() = 0
00:47:24.487286 sync() = 0
00:47:24.587181 sync() = 0
00:47:24.687237 sync() = 0
Also, on top the above, creating and processing a timer requires 3
syscalls: timerfd_create, timerfd_gettime and read vs 0 if we keep the
min-heap.
Given that UV periodic timer is just an API sugar over the regular
timer, would not make sense that the loop execution time is taken into
account when setting the next timer period?
This is:
- Run periodic timer with interval 100 ms.
- First loop iteration takes 15 ms.
- Somehow libuv knows that and set the timer next period on 85 ms.
Just wondering.
Your idea is interesting. After reading the reactions on my initial post, I wonder if it's a constructive proposal to split the question into multiples aspects:1) Should libuv offer API for periodic timer ? The actual implementation do not and in fact correspond to a one shot timer restarted at the end of the callback. If the response is no, then actual API and documentation should be changed. If the response is yes, the implementation should be changed. I hope that the libuv community found an advantage to respond yes to this question, as periodic timers is certainly a common feature request and libuv is in best place to implement it.
2) Should libuv use timerfd to implement the aspect 1 in case the response is yes ? Certainly no in general as timerfd is usable only on Linux starting from kernel 2.6.23 or so. Depending on the performances of the general code for periodic timer (if there is any) timerfd might allow an improvement, but this is too early to be certain about that at this stage.
3) Should libuv offer a high precision timer API ? From a API point of view, it would be better to have a single API that scale and stay precise. An example on how to use timerfd watcher will be an immediate advantage for not too old Linux kernel users.
Your idea is interesting. After reading the reactions on my initial post, I wonder if it's a constructive proposal to split the question into multiples aspects:1) Should libuv offer API for periodic timer ? The actual implementation do not and in fact correspond to a one shot timer restarted at the end of the callback. If the response is no, then actual API and documentation should be changed. If the response is yes, the implementation should be changed. I hope that the libuv community found an advantage to respond yes to this question, as periodic timers is certainly a common feature request and libuv is in best place to implement it.
I don't think so. The current model was inherited from libev, which had no concept of "requests" like libuv does, instead it had only "handles".
Also the earlier versions of libuv didn't support `uv_cancel(uv_req_t*)` so at the time we had to make a timer a handle to support stopping the timer.
Saùl, Ben and myself already had some sort of informal agreement that a next iteration of libuv would only support one-shot timers with an API similar to this:
`uv_timeout(uv_timeout_req_t* timeout, int64_t timeout, uv_timeout_cb callback);
2) Should libuv use timerfd to implement the aspect 1 in case the response is yes ? Certainly no in general as timerfd is usable only on Linux starting from kernel 2.6.23 or so. Depending on the performances of the general code for periodic timer (if there is any) timerfd might allow an improvement, but this is too early to be certain about that at this stage.
I don't think we should use timerfd for uv_timer / uv_timeout timers. These timers are guaranteed to be fast and highly scalable, not precise. If we use timerfd on some linux flavors, they will be slow-and-precise on some operating systems, and fast-and-coarse on others. It makes libuv as a whole less useful.
3) Should libuv offer a high precision timer API ? From a API point of view, it would be better to have a single API that scale and stay precise. An example on how to use timerfd watcher will be an immediate advantage for not too old Linux kernel users.
Maybe - I like to think use cases; what are you trying to do? Writing a game loop, rendering video, synchonizing clocks?
2014-09-30 13:52 GMT+02:00 Bert Belder:
> next iteration of libuv would only support one-shot timers with an API
> similar to this:
> `uv_timeout(uv_timeout_req_t* timeout, int64_t timeout, uv_timeout_cb
> callback);
While that is great it also completely drops the "periodic timer"
feature from libuv. Ok, current periodic timers are wrong but, should
libuv provide correct periodic timers (those in which the callback
execution time does not affect the next execution)?
By just providing the uv_timeout() request, users cannot implement
real periodic timers.
But I can't really think of any valid use case for this, which makes it hard to tell whether any api is actually useful.
I am not so much in favor of adding features that nobody really needs (yet), which is why I'm asking for the use case the TS needs it for or has in mind.
Le mardi 30 septembre 2014 17:26:10 UTC+2, Bert Belder a écrit :
But I can't really think of any valid use case for this, which makes it hard to tell whether any api is actually useful.
I am not so much in favor of adding features that nobody really needs (yet), which is why I'm asking for the use case the TS needs it for or has in mind.Sorry, I have a radical different view. I build Linux embedded system since more than 15 years and I can't remember a single one that don't use periodic timer.
Most of the times this is related to the hardware
or user interface where it is expected to not have delay that depend of a callback execution time to get a smooth operation.
On Tuesday, September 30, 2014 6:10:23 PM UTC+2, Jean-Christian de Rivaz wrote:Le mardi 30 septembre 2014 17:26:10 UTC+2, Bert Belder a écrit :
But I can't really think of any valid use case for this, which makes it hard to tell whether any api is actually useful.
I am not so much in favor of adding features that nobody really needs (yet), which is why I'm asking for the use case the TS needs it for or has in mind.Sorry, I have a radical different view. I build Linux embedded system since more than 15 years and I can't remember a single one that don't use periodic timer.
Note that I was speaking of a high-precision periodic timer.
I'm saying that a sloppy one (as sloppy as we have today or slighly better) can easily be built on top of a one-shot timer.
I am curious for one these embedded systems used high-precision (periodic or not) timers.
Most of the times this is related to the hardware
Maybe on embedded systems, I don't know. Can you give me examples of hardware other than the display (see below for that)?
Are you trying to do something very realtime like controlling a robot?
or user interface where it is expected to not have delay that depend of a callback execution time to get a smooth operation.
I think for user interfaces 60fps is generally considered good enough.
This requires a timer with at most a (1000 / 60) ≈ 16ms interval, which is well within the range of what the current timer implementation can do.