On 09/29/2014 08:24 AM, Saúl Ibarra Corretgé wrote:
> Hi Jean-Christian,
>
> On 09/29/2014 01:06 AM, Jean-Christian de Rivaz wrote:
>> Hello,
>>
>> I tried to use libuv on Linux for an application that require a precise
>> periodicity. I observed that uv_timer_start(, ,100, 100) make the
>> repetitive epoll() always wait a bit more than 100ms, regardless of the
>> callback function execution time (strace -T):
>> |
>> epoll_wait(5,{},1024,99) =0<0.099287> <=Firstepoll()wait 99.287ms
>> sync() =0<0.054469>
>> epoll_wait(5,{},1024,100) =0<0.100211> <=Secondepoll()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> <===
>> |
>> I use the sync() in the callback to very simply add a execution of about
>> from 40ms to 50ms on the test machine, the final application is more
>> complex than that, this is just to keep the example as simple as
>> possible. After the first epoll(), all epoll() have a similar length of
>> a bit more that 100ms. This already too long delay is in addition to the
>> delay of the sync() call. In fine, the period of this example is between
>> 140ms and 150ms instead of the expected 100ms. If I filter the sync()
>> call time I get this (strace -tt):
>> |
>> 00:31:27.960802sync() =0
>> 00:31:28.106703sync() =0
>> 00:31:28.250530sync() =0
>> 00:31:28.391060sync() =0
>> 00:31:28.529861sync() =0
>> 00:31:28.669751sync() =0
>> 00:31:28.810477sync() =0
>> 00:31:28.949302sync() =0
>> |
>> The jitter of the sync() call time is very big, probably equal to the
>> callback execution time.
>>
>> I tested timerfd_create() on the same machine with a loop of read() on
>> the timerfd file and sync(). The result is very different (strace -T):
>> |
>> 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> <==Firstread()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> <=Secondread()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> <===
>> |
>> The read() delay compensate exactly the sync() delay to make a
>> periodicity of exactly 100ms. If I filter the sync() call time I get
>> this (strace -tt):
>> |
>> 00:47:23.687205sync() =0
>> 00:47:23.787220sync() =0
>> 00:47:23.887393sync() =0
>> 00:47:23.987276sync() =0
>> 00:47:24.087210sync() =0
>> 00:47:24.187164sync() =0
>> 00:47:24.287242sync() =0
>> 00:47:24.387330sync() =0
>> 00:47:24.487286sync() =0
>> 00:47:24.587181sync() =0
>> 00:47:24.687237sync() =0
>> |
>> The jitter of the sync() call time is smaller than 1ms, something that
>> the current libuv is unable to do.
>>
>
> Periodic timers are a bit hard. Some people expect that the timer
> compensates for the time spent in the callback, some don't cause they
> want the interval to be preserved across callbacks. It's also quite
> messy to handle the case in which the callback takes longer than the
> next interval.
>
> Having that said, timers on libuv don't compensate for the amount of
> time spent in the callback.
>
>> I have two questions:
>> 1) is there anything that would prevent libuv from
>> using timerfd_settime() on Linux ?
>
> There are a couple I can think of: timerfd was added in Linux 2.6.22,
> and I believe we still support older kernels, but more importantly,
> timerfd would create a file descriptor per timer, that's one million fds
> if we have one million timers, vs 0 fds which the current implementation
> uses.
>
>> 2) Is there any motivation to do that ?
>>
>
> Hopefully others chime in as well, but I'm not really inclined to go
> this route, for the aforementioned reasons. I'm open to be proven
> otherwise though :-)
>
>
> Regards,
> 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. -- Saúl Ibarra Corretgé bettercallsaghul.com
signature.asc
Description: OpenPGP digital signature
