mat*_*ari 62 javascript memory-leaks setinterval
目前正在开发基于JavaScript的动画项目.
我注意到,正确使用setInterval(),setTimeout()甚至在requestAnimationFrame没有我的请求的情况下分配内存,并导致频繁的垃圾收集调用.更多GC调用=闪烁:-(
例如; 当我通过在谷歌浏览器中调用init()执行以下简单代码时,内存分配+垃圾收集在前20-30秒内没问题......
function init()
{
var ref = window.setInterval(function() { draw(); }, 50);
}
function draw()
{
return true
}
Run Code Online (Sandbox Code Playgroud)
不知何故,在一分钟左右的时间内,开始分配内存的奇怪增加!由于init()仅被调用一次,所以分配的内存大小增加的原因是什么?
(编辑:chrome截图上传)

注意#1:是的,我尝试在下一个setInterval()之前调用clearInterval().问题依然存在!
注意#2:为了隔离问题,我保持上面的代码简单而愚蠢.
Luq*_*aan 52
编辑:Yury的答案更好.
tl;博士IMO没有内存泄漏.正斜率只是setInterval和setTimeout的效果.收集垃圾,如锯齿图案所示,意味着没有内存泄漏.(我认为).
我不确定是否有办法解决这种所谓的"内存泄漏".在这种情况下,"内存泄漏"是指对setInterval函数的每次调用都会增加内存使用量,如内存分析器中的正斜率所示.
实际情况是没有实际的内存泄漏:垃圾收集器仍然能够收集内存.根据定义,内存泄漏"发生在计算机程序获取内存但无法将其释放回操作系统时."
如下面的内存配置文件所示,内存泄漏未发生.每次函数调用时内存使用量都在增加.OP期望因为这是被反复调用的相同函数,所以应该没有内存增加.然而,这种情况并非如此.每个函数调用都会消耗内存.最终,收集垃圾,创造锯齿图案.
我已经探索了几种重新排列间隔的方法,它们都导致了相同的锯齿模式(尽管一些尝试导致垃圾收集永远不会发生,因为参考被保留).
function doIt() {
console.log("hai")
}
function a() {
doIt();
setTimeout(b, 50);
}
function b() {
doIt();
setTimeout(a, 50);
}
a();
Run Code Online (Sandbox Code Playgroud)
http://fiddle.jshell.net/QNRSK/14/

function b() {
var a = setInterval(function() {
console.log("Hello");
clearInterval(a);
b();
}, 50);
}
b();
Run Code Online (Sandbox Code Playgroud)
http://fiddle.jshell.net/QNRSK/17/

function init()
{
var ref = window.setInterval(function() { draw(); }, 50);
}
function draw()
{
console.log('Hello');
}
init();
Run Code Online (Sandbox Code Playgroud)
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();?
Run Code Online (Sandbox Code Playgroud)
http://fiddle.jshell.net/QNRSK/21/

显然setTimeout,setInterval并不是Javascript的正式部分(因此它们不是v8的一部分).实施由实施者决定.我建议你看看node.js中setInterval的实现
Yur*_*sky 29
这里的问题不在代码本身,它不泄漏.这是因为Timeline面板的实现方式.当Timeline记录事件时,我们会在每次调用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
我想回复你关于setInterval和闪烁的评论:
我注意到,正确使用setInterval(),setTimeout()甚至requestAnimationFrame都会在没有请求的情况下分配内存,并导致频繁的垃圾回收调用.更多GC调用=闪烁:-(
您可能想尝试使用基于setTimeout 的较不邪恶的自调用函数替换setInterval调用.保罗爱尔兰提到这在谈话称为10件事情我从jQuery源教训(视频这里,注意到这里看到#2).你所做的是将你对setInterval的调用替换为一个函数,该函数在完成它应该做的工作之后通过setTimeout间接调用它自己.引用话题:
许多人认为setInterval是一个邪恶的功能.无论函数是否完成,它都会以指定的时间间隔调用函数.
使用上面的示例代码,您可以从以下位置更新init函数:
function init()
{
var ref = window.setInterval(function() { draw(); }, 50);
}
Run Code Online (Sandbox Code Playgroud)
至:
function init()
{
//init stuff
//awesome code
//start rendering
drawLoop();
}
function drawLoop()
{
//do work
draw();
//queue more work
setTimeout(drawLoop, 50);
}
Run Code Online (Sandbox Code Playgroud)
这应该有点帮助,因为:
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
36895 次 |
| 最近记录: |