alternate approach to timer inaccuracy due to cached times
Marc Lehmann
schmorp at schmorp.de
Thu Oct 13 08:48:40 CEST 2011
On Tue, Oct 11, 2011 at 05:15:54PM -0700, Shaun Lindsay <srlindsay at gmail.com> wrote:
> Hello,
Hi!
> As mentioned in the above link, you can force an update of the cached time
> via ev_update_now(), but this doesn't practically address the issue.
Well, it should address the issue, thats what it is made for - why do you
think it doesn't address the issue?
> case, the triggering of any of the timeouts would constitute an error case,
> so I'd need to call ev_update_now() before every timer start.
In most cases, you would have events that invalidate the error case -
having these at higher priority would solve that problem in a better way.
> timeouts where immediate, nondeterministic expiration is an acceptable
> condition,
You are not talking about libev, are you? Even without calling
ev_update_now there is nothing nondeterministic, and timers don't timeout
immediately in any case.
> time for every timer anyway. From a gevent perspective, it also becomes
> difficult to expose the update call in a sane way to the user, since the
> event architecture is hidden beneath the greenlet/coroutine abstraction.
I can't say much about gevent, but that seems to indicate a design issue
with gevent to me.
> Deferring calls ev_timer_start to the end of the dispatch cycle, then
> starting them in a batch would fix this issue.
Well, it doesn't make anything more deterministic, or avoids timers timing
out immediately, you are just trading one behaviour for another.
> One nice advantage of this approach is that under heavy load, the timeouts
> will occur later than the requested time, rather than before the requested
Libev guarantees that timeouts never trigger before the requested time
already.
> time, which seems saner from an application perspective -- I'd rather have a
> 100ms timeout fire at 200ms than fire in 0ms.
The latter can only happen if you use two different clocks to compare
times. This is rather meaningless - libev will never timeout a timer
requesting a 100ms timeout before or even at 100ms after the requested time.
> probably need modification to be consistent, like adding a struct ev_timer
> *next to all ev_timers for use in a linked list, for instance. I'm also not
Unrelated to the problem: the libev way of doing things would be to have
an array for those timers, which would likely be faster and save some
memory.
> Now that I think about it, timers started by callbacks from other timers
> might not get picked up until the next event cycle, which might be bad, I'm
> not sure. Somebody more familiar with the code can probably point me in the
> right direction on that.
I think if you are hitting such a problem in gevent, this is a design issue
in gevent - any event system should be able to deal with delays in event
processing in a sane way.
Fixing the desing might be hard, though, but since gevent doesn't expose
libev, adding an ev_update_now before creating a timer seems like an easy
workaround (after all, other high-performance event libraries do that too
:)
If this is only important for some timers, you could either do it only for
those, or base your timings on ev_time(), as described in the manpage.
And last not least, you could easily implement this in gevent, where it
probably belongs, as it works around a (probably minor) design limitation
in gevent.
--
The choice of a Deliantra, the free code+content MORPG
-----==- _GNU_ http://www.deliantra.net
----==-- _ generation
---==---(_)__ __ ____ __ Marc Lehmann
--==---/ / _ \/ // /\ \/ / schmorp at schmorp.de
-=====/_/_//_/\_,_/ /_/\_\
More information about the libev
mailing list