diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2012-12-18 07:20:39 +0100 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2012-12-18 16:16:33 +0100 |
commit | d607d856afc744b1e6bc42cdb9b67b6c4e7e4876 (patch) | |
tree | cff49b3198dedc44a3d2bf424958674ee5280e50 | |
parent | 8ccfed2edceb9b4c216ce885d76fa03537e3eb5e (diff) | |
download | node-d607d856afc744b1e6bc42cdb9b67b6c4e7e4876.tar.gz |
node: remove idle gc
Remove the idle garbage collector. Its purpose was to run the garbage collector
when the application is idle but it never worked quite right. Many people have
complained over the years that with heaps > 128 MB, a node.js process never
sleeps anymore; instead, it spends nearly 100% of its CPU time trying to
collect garbage.
Back in the old days, idle GC probably was a good idea. But with V8's current
incremental collector, idle gc appears to offer no time or space benefits
whatsoever and indeed seems actively harmful. Remove it.
Fixes #3870.
-rw-r--r-- | src/node.cc | 104 |
1 files changed, 0 insertions, 104 deletions
diff --git a/src/node.cc b/src/node.cc index 6341ec3f7..3e8d2d615 100644 --- a/src/node.cc +++ b/src/node.cc @@ -147,78 +147,9 @@ static bool use_sni = true; static bool use_sni = false; #endif -// We need to notify V8 when we're idle so that it can run the garbage -// collector. The interface to this is V8::IdleNotification(). It returns -// true if the heap hasn't be fully compacted, and needs to be run again. -// Returning false means that it doesn't have anymore work to do. -// -// A rather convoluted algorithm has been devised to determine when Node is -// idle. You'll have to figure it out for yourself. -static uv_check_t gc_check; -static uv_idle_t gc_idle; -static uv_timer_t gc_timer; -bool need_gc; - // process-relative uptime base, initialized at start-up static double prog_start_time; -#define FAST_TICK 700. -#define GC_WAIT_TIME 5000. -#define RPM_SAMPLES 100 -#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES] -static int64_t tick_times[RPM_SAMPLES]; -static int tick_time_head; - -static void CheckStatus(uv_timer_t* watcher, int status); - -static void StartGCTimer () { - if (!uv_is_active((uv_handle_t*) &gc_timer)) { - uv_timer_start(&gc_timer, node::CheckStatus, 5000, 5000); - } -} - -static void StopGCTimer () { - if (uv_is_active((uv_handle_t*) &gc_timer)) { - uv_timer_stop(&gc_timer); - } -} - -static void Idle(uv_idle_t* watcher, int status) { - assert((uv_idle_t*) watcher == &gc_idle); - - if (V8::IdleNotification()) { - uv_idle_stop(&gc_idle); - StopGCTimer(); - } -} - - -// Called directly after every call to select() (or epoll, or whatever) -static void Check(uv_check_t* watcher, int status) { - assert(watcher == &gc_check); - - tick_times[tick_time_head] = uv_now(uv_default_loop()); - tick_time_head = (tick_time_head + 1) % RPM_SAMPLES; - - StartGCTimer(); - - for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) { - double d = TICK_TIME(i+1) - TICK_TIME(i+2); - //printf("d = %f\n", d); - // If in the last 5 ticks the difference between - // ticks was less than 0.7 seconds, then continue. - if (d < FAST_TICK) { - //printf("---\n"); - return; - } - } - - // Otherwise start the gc! - - //fprintf(stderr, "start idle 2\n"); - uv_idle_start(&gc_idle, node::Idle); -} - static void Tick(void) { // Avoid entering a V8 scope. @@ -1747,31 +1678,6 @@ v8::Handle<v8::Value> Exit(const v8::Arguments& args) { } -static void CheckStatus(uv_timer_t* watcher, int status) { - assert(watcher == &gc_timer); - - // check memory - if (!uv_is_active((uv_handle_t*) &gc_idle)) { - HeapStatistics stats; - V8::GetHeapStatistics(&stats); - if (stats.total_heap_size() > 1024 * 1024 * 128) { - // larger than 128 megs, just start the idle watcher - uv_idle_start(&gc_idle, node::Idle); - return; - } - } - - double d = uv_now(uv_default_loop()) - TICK_TIME(3); - - //printfb("timer d = %f\n", d); - - if (d >= GC_WAIT_TIME - 1.) { - //fprintf(stderr, "start idle\n"); - uv_idle_start(&gc_idle, node::Idle); - } -} - - static Handle<Value> Uptime(const Arguments& args) { HandleScope scope; double uptime; @@ -2959,16 +2865,6 @@ char** Init(int argc, char *argv[]) { uv_idle_init(uv_default_loop(), &tick_spinner); - uv_check_init(uv_default_loop(), &gc_check); - uv_check_start(&gc_check, node::Check); - uv_unref(reinterpret_cast<uv_handle_t*>(&gc_check)); - - uv_idle_init(uv_default_loop(), &gc_idle); - uv_unref(reinterpret_cast<uv_handle_t*>(&gc_idle)); - - uv_timer_init(uv_default_loop(), &gc_timer); - uv_unref(reinterpret_cast<uv_handle_t*>(&gc_timer)); - V8::SetFatalErrorHandler(node::OnFatalError); // Fetch a reference to the main isolate, so we have a reference to it |