JavaScript setInterval()方法是否会导致内存泄漏?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (19)

目前正在开发基于JavaScript的动画项目。

我注意到,正确使用setInterval()setTimeout()甚至requestAnimationFrame没有我的请求分配内存,并导致频繁的垃圾收集调用。更多GC调用=闪烁:-(

例如; 当我通过在谷歌浏览器中调用init()来执行以下简单代码时,内存分配+垃圾回收在前20-30秒内可以正常运行......

function init()
{
    var ref = window.setInterval(function() { draw(); }, 50);
}

function draw()
{
    return true
}

不知何故,在一分钟左右的时间内,分配的内存开始奇怪的增加!由于init()仅被调用一次,分配内存大小增加的原因是什么?

(chrome截图上传)

注#1:是的,我已经尝试在下一个setInterval()之前调用clearInterval()。问题依旧!

注#2:为了隔离问题,我保持上面的代码简单和愚蠢。

提问于
用户回答回答于

这里的问题不在代码本身,它不泄漏。这是因为时间轴面板的实现方式。当时间轴记录事件时,我们会在每次调用setInterval回调时收集JavaScript堆栈跟踪。堆栈跟踪首先在JS堆中分配,然后复制到本地数据结构中,堆栈跟踪复制到本地事件后,它在JS堆中变成垃圾。这反映在图表上。禁用以下调用http://trac.webkit.org/browser/trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp#L55

存在与此问题相关的错误:https : //code.google.com/p/chromium/issues/detail?id=120186

用户回答回答于

编辑:尤里的答案是更好的。

tl;医生国际海事组织没有内存泄漏。正斜率只是setInterval和setTimeout的效果。收集的垃圾如锯齿图案所示,意思是没有内存泄漏。(我认为)。

我不确定是否有办法解决这个所谓的“内存泄漏”。在这种情况下,“内存泄漏”是指每次调用setInterval函数都会增加内存使用情况,如内存分析器中的正斜率所示。

实际情况是没有实际的内存泄漏:垃圾收集器仍然能够收集内存。内存泄漏按照定义“在计算机程序获取内存但未能将其释放回操作系统时发生。”

如下面的内存配置文件所示,内存泄漏未发生。内存使用量随着每个函数调用而增加。OP期望,因为这是一遍又一遍被调用的相同函数,所以不应该增加内存。然而,这种情况并非如此。每个函数调用都会消耗内存。最终收集垃圾,创建锯齿图案。

我已经探索了重新排列间隔的几种方法,并且它们都导致相同的锯齿图案(尽管有些尝试导致垃圾收集从不发生,因为保留了引用)。

function doIt() {
    console.log("hai")
}

function a() {
    doIt();
    setTimeout(b, 50);
}
function b() {
    doIt();
    setTimeout(a, 50);
}

a();

http://fiddle.jshell.net/QNRSK/14/

function b() {
    var a = setInterval(function() {
        console.log("Hello");
        clearInterval(a);
        b();                
    }, 50);
}
b();

http://fiddle.jshell.net/QNRSK/17/

function init()
{
    var ref = window.setInterval(function() { draw(); }, 50);
}
function draw()
{
    console.log('Hello');
}
init();

http://fiddle.jshell.net/QNRSK/20/

function init()
{
    window.ref = window.setInterval(function() { draw(); }, 50);
}
function draw()
{
    console.log('Hello');
    clearInterval(window.ref);
    init();
}
init();​

http://fiddle.jshell.net/QNRSK/21/

显然setTimeoutsetInterval并不是Javascript的正式部分(因此它们不是v8的一部分)。实施由实施者决定。我建议你看一下在Node.js中setInterval等的实现

扫码关注云+社区