Skip to content

Commit d607d85

Browse files
committed
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.
1 parent 8ccfed2 commit d607d85

File tree

1 file changed

+0
-104
lines changed

1 file changed

+0
-104
lines changed

src/node.cc

-104
Original file line numberDiff line numberDiff line change
@@ -147,78 +147,9 @@ static bool use_sni = true;
147147
static bool use_sni = false;
148148
#endif
149149

150-
// We need to notify V8 when we're idle so that it can run the garbage
151-
// collector. The interface to this is V8::IdleNotification(). It returns
152-
// true if the heap hasn't be fully compacted, and needs to be run again.
153-
// Returning false means that it doesn't have anymore work to do.
154-
//
155-
// A rather convoluted algorithm has been devised to determine when Node is
156-
// idle. You'll have to figure it out for yourself.
157-
static uv_check_t gc_check;
158-
static uv_idle_t gc_idle;
159-
static uv_timer_t gc_timer;
160-
bool need_gc;
161-
162150
// process-relative uptime base, initialized at start-up
163151
static double prog_start_time;
164152

165-
#define FAST_TICK 700.
166-
#define GC_WAIT_TIME 5000.
167-
#define RPM_SAMPLES 100
168-
#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
169-
static int64_t tick_times[RPM_SAMPLES];
170-
static int tick_time_head;
171-
172-
static void CheckStatus(uv_timer_t* watcher, int status);
173-
174-
static void StartGCTimer () {
175-
if (!uv_is_active((uv_handle_t*) &gc_timer)) {
176-
uv_timer_start(&gc_timer, node::CheckStatus, 5000, 5000);
177-
}
178-
}
179-
180-
static void StopGCTimer () {
181-
if (uv_is_active((uv_handle_t*) &gc_timer)) {
182-
uv_timer_stop(&gc_timer);
183-
}
184-
}
185-
186-
static void Idle(uv_idle_t* watcher, int status) {
187-
assert((uv_idle_t*) watcher == &gc_idle);
188-
189-
if (V8::IdleNotification()) {
190-
uv_idle_stop(&gc_idle);
191-
StopGCTimer();
192-
}
193-
}
194-
195-
196-
// Called directly after every call to select() (or epoll, or whatever)
197-
static void Check(uv_check_t* watcher, int status) {
198-
assert(watcher == &gc_check);
199-
200-
tick_times[tick_time_head] = uv_now(uv_default_loop());
201-
tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
202-
203-
StartGCTimer();
204-
205-
for (int i = 0; i < (int)(GC_WAIT_TIME/FAST_TICK); i++) {
206-
double d = TICK_TIME(i+1) - TICK_TIME(i+2);
207-
//printf("d = %f\n", d);
208-
// If in the last 5 ticks the difference between
209-
// ticks was less than 0.7 seconds, then continue.
210-
if (d < FAST_TICK) {
211-
//printf("---\n");
212-
return;
213-
}
214-
}
215-
216-
// Otherwise start the gc!
217-
218-
//fprintf(stderr, "start idle 2\n");
219-
uv_idle_start(&gc_idle, node::Idle);
220-
}
221-
222153

223154
static void Tick(void) {
224155
// Avoid entering a V8 scope.
@@ -1747,31 +1678,6 @@ v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
17471678
}
17481679

17491680

1750-
static void CheckStatus(uv_timer_t* watcher, int status) {
1751-
assert(watcher == &gc_timer);
1752-
1753-
// check memory
1754-
if (!uv_is_active((uv_handle_t*) &gc_idle)) {
1755-
HeapStatistics stats;
1756-
V8::GetHeapStatistics(&stats);
1757-
if (stats.total_heap_size() > 1024 * 1024 * 128) {
1758-
// larger than 128 megs, just start the idle watcher
1759-
uv_idle_start(&gc_idle, node::Idle);
1760-
return;
1761-
}
1762-
}
1763-
1764-
double d = uv_now(uv_default_loop()) - TICK_TIME(3);
1765-
1766-
//printfb("timer d = %f\n", d);
1767-
1768-
if (d >= GC_WAIT_TIME - 1.) {
1769-
//fprintf(stderr, "start idle\n");
1770-
uv_idle_start(&gc_idle, node::Idle);
1771-
}
1772-
}
1773-
1774-
17751681
static Handle<Value> Uptime(const Arguments& args) {
17761682
HandleScope scope;
17771683
double uptime;
@@ -2959,16 +2865,6 @@ char** Init(int argc, char *argv[]) {
29592865

29602866
uv_idle_init(uv_default_loop(), &tick_spinner);
29612867

2962-
uv_check_init(uv_default_loop(), &gc_check);
2963-
uv_check_start(&gc_check, node::Check);
2964-
uv_unref(reinterpret_cast<uv_handle_t*>(&gc_check));
2965-
2966-
uv_idle_init(uv_default_loop(), &gc_idle);
2967-
uv_unref(reinterpret_cast<uv_handle_t*>(&gc_idle));
2968-
2969-
uv_timer_init(uv_default_loop(), &gc_timer);
2970-
uv_unref(reinterpret_cast<uv_handle_t*>(&gc_timer));
2971-
29722868
V8::SetFatalErrorHandler(node::OnFatalError);
29732869

29742870
// Fetch a reference to the main isolate, so we have a reference to it

0 commit comments

Comments
 (0)