主线程繁忙时能否进行垃圾回收?

时间:2018-10-10 12:39:53

标签: javascript node.js garbage-collection v8

假设我的循环很长:

// Let's say this loop takes 10 seconds to execute
for(let i = 0; i <= 1000000; ++i) {
    const garbage = { i };
    // some other code
}

垃圾收集器可以在循环期间运行,还是只能在应用程序空闲时运行?

我没有找到与此相关的任何文档,但是因为Node.js具有--nouse-idle-notification,从理论上讲它禁用了GC,所以我认为GC仅在发送空闲通知时运行(当主线程不忙)。

之所以问这个问题,是因为我的循环有时会在执行时间出现尖峰,并想知道GC是否有可能在循环期间运行,从而导致滞后尖峰。

2 个答案:

答案 0 :(得分:2)

V8开发人员在这里。简短的答案是,GC可以随时运行,并且可以在需要时运行。

请注意,GC是一个相当复杂的系统:它执行几个不同的任务,并且大多数任务以增量步骤和/或与主线程同时执行。特别是,每次分配都会触发一点增量GC工作。 (这暗示着通过非常小心地避免所有分配,您可以构造不会在运行时导致GC活动的循环;但是,循环永远不会堆积无法收集的垃圾-除非您的计算机中存在泄漏代码,当然是无意间保持对象可达。)

  

垃圾收集器可以在循环期间运行,还是只能在应用程序空闲时运行?

它绝对可以并且将在循环中运行。

  

Node.js具有--nouse-idle-notification,从理论上讲它禁用了GC

不,不是。无法禁用GC。该标志禁用了一种触发GC活动的特定机制,但这仅意味着GC将被其他机制触发。

  

GC仅在发送空闲通知(主线程不忙时)时运行

不,我们的想法是在空闲时间运行一些 extra GC周期,以在应用程序不忙时节省一些内存。

  

我的循环有时会在执行时间出现尖峰,并想知道GC是否可能在循环期间运行,从而导致滞后尖峰

可能是。它可能也可能与功能的优化或反优化有关。也可能是其他原因-例如,操作系统中断您的进程或将其分配给另一个CPU内核,或其他数百种原因。计算机是复杂的机器;-)

  

如果将变量设置为null,则会立即完成垃圾回收

不,不是。垃圾回收永远不会立即完成(至少在V8中不是这样)。

答案 1 :(得分:0)

作为一个概念,垃圾收集器在单独的线程中工作,因为这样就不会阻塞主线程(大多数情况下是UI线程)。

对于您的示例,垃圾回收线程在与此循环“并行”运行时没有问题,因为只要const garbage = {key: i}处的值referenced都不会被删除。

还请注意,有several generations垃圾收集器会在完全删除它们之前将它们传递给值。

相关问题