From ea4956f0465e5ea1109283f161c6ec43c30d722c Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Sat, 20 Feb 2010 20:36:31 -0800 Subject: [PATCH] Simplify call to V8::IdleNotification Run a max priority ev_timer every 2 seconds. If there aren't any pending watchers then call V8::IdleNotification() once. This is slower at freeing memory, but I think simpler and less aggressive. --- src/node.cc | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/src/node.cc b/src/node.cc index 408bd86588..d63ec6cb70 100644 --- a/src/node.cc +++ b/src/node.cc @@ -68,32 +68,17 @@ static ev_async eio_want_poll_notifier; static ev_async eio_done_poll_notifier; static ev_idle eio_poller; -static ev_idle gc_idle_watcher; static ev_timer gc_timer; -#define GC_INTERVAL 1.0 +#define GC_INTERVAL 2.0 -// Node calls this every GC_INTERVAL seconds in order to try -// and turn on the gc_idle_watcher, which will eventually (when the process -// isn't busy) call the GC +// Node calls this every GC_INTERVAL seconds in order to try and call the +// GC. This watcher is run with maximum priority, so ev_pending_count() == 0 +// is an effective measure of idleness. static void GCTimeout(EV_P_ ev_timer *watcher, int revents) { assert(watcher == &gc_timer); assert(revents == EV_TIMER); - - if (ev_pending_count() == 0 && !ev_is_active(&gc_idle_watcher)) { - ev_idle_start(EV_DEFAULT_UC_ &gc_idle_watcher); - ev_unref(EV_DEFAULT_UC); - } -} - - -static void DoGC(EV_P_ ev_idle *watcher, int revents) { - assert(watcher == &gc_idle_watcher); - assert(revents == EV_IDLE); - if (V8::IdleNotification()) { - ev_ref(EV_DEFAULT_UC); - ev_idle_stop(EV_DEFAULT_UC_ watcher); - } + if (ev_pending_count() == 0) V8::IdleNotification(); } @@ -1154,12 +1139,13 @@ int main(int argc, char *argv[]) { ev_default_loop(EVFLAG_AUTO); - // The idle watcher which will call GC - ev_idle_init(&node::gc_idle_watcher, node::DoGC); - ev_set_priority(&node::gc_idle_watcher, EV_MINPRI); - // The check for pending events (will start the idle watcher) ev_timer_init(&node::gc_timer, node::GCTimeout, GC_INTERVAL, GC_INTERVAL); - ev_set_priority(&node::gc_timer, EV_MINPRI); + // Set the gc_timer to max priority so that it runs before all other + // watchers. In this way it can check if the 'tick' has other pending + // watchers by using ev_pending_count() - if it ran with lower priority + // then the other watchers might run before it - not giving us good idea + // of loop idleness. + ev_set_priority(&node::gc_timer, EV_MAXPRI); ev_timer_start(EV_DEFAULT_UC_ &node::gc_timer); ev_unref(EV_DEFAULT_UC);