在测试我们的Javascript库时,我认为我们在IE10(v10.0.9200.16519 - Windows 8 64位)Javascript实现setInterval
中发现了严重的内存泄漏。解决方法IE10 setInterval内存泄漏
一个简单的测试案例表明,如果一个变量在作为参数传递的函数的闭包中被捕获以供后续执行,它似乎没有资格进行垃圾回收,即浏览器似乎仍然持有引用到函数或者至少是闭包变量。
我们的测试用例执行setInterval
功能只有一次,然后没有代码被运行了一段时间后,清除间隔定时器,即没有变量访问了(据我可以看到没有全局介绍了在这段代码中,除了该方法在onload
中运行),但该进程占用了半个千兆字节的内存(取决于迭代次数)。
有趣的是,如果我们使用setTimeout
方法,而不是(也问题不似乎没有在IE9存在,和目前版本的Chrome,FF)不会发生这种情况。
该问题可以通过this fiddle查看。
在Windows 8上的IE10的新实例中运行它,并打开任务管理器以查看内存使用情况。它将快速增长到350兆字节,并在脚本执行后停留在那里。
这是有问题的代码块的重要组成部分:
// the function that when called multiple times will cause the leak in IE10
var eatMemory = function() {
var a = null; // the captured closure variable
var intervalId = setInterval(function() {
a = createBigArray(); // call a method that allocates a lot of memory
clearInterval(intervalId); // stop the interval timer
}, 100);
}
(我知道这是很容易解决这个特定一段代码但是,这不是问题的关键 - 这仅仅是最小的。一段代码,我们想出了能重现问题,真正的代码实际上捕获在封闭this
和对象是永远不会被垃圾收集。)
有没有在我们的代码中的bug或者有使用setInterval
其中一种方式一个闭包变量持有对al的引用arge对象,而不会触发内存泄漏并且不会恢复为“递归”调用?
(我也posted the question on MSDN)
更新:这个问题也存在于IE10在Windows 7上,但如果切换到IE9标准的模式不存在。我将此提交给MS Connect并报告进度。
更新:微软accepted the issue并报告它被固定在IE11(预览版) - 我没有这个确认自己,但
更新: IE 11已经正式发布(人?)并且我无法使用我的系统(Win 8.1 Pro 64bit)再现该版本的问题。由回落到setTimeout
正如我已经写了(和评论者建议),这可以被合作周围(不固定):
你为什么要创建一个间隔,然后立即将其清除?这不是破坏目的吗? – 2013-04-09 15:13:42
@BradM我用一个解释更新了问题 - 真实的代码比这更复杂,并不总是无条件地清除间隔。 – Sebastian 2013-04-09 15:18:53
您是否尝试过不使用匿名函数,而是使用函数引用 - 之后显式覆盖此引用? – CBroe 2013-04-09 15:22:00