假设我的循环很长:
// 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是否有可能在循环期间运行,从而导致滞后尖峰。
答案 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垃圾收集器会在完全删除它们之前将它们传递给值。