使用Chrome查找JavaScript内存泄漏
我创建了一个非常简单的测试用例,它创建了一个Backbone视图,将一个处理程序附加到一个事件,并实例化一个用户定义的类。 我相信通过单击此示例中的“删除”按钮,所有内容都将被清除,并且不应该有内存泄漏。
代码的jsfiddle在这里:http://jsfiddle.net/4QhR2/
// scope everything to a function
function main() {
function MyWrapper() {
this.element = null;
}
MyWrapper.prototype.set = function(elem) {
this.element = elem;
}
MyWrapper.prototype.get = function() {
return this.element;
}
var MyView = Backbone.View.extend({
tagName : "div",
id : "view",
events : {
"click #button" : "onButton",
},
initialize : function(options) {
// done for demo purposes only, should be using templates
this.html_text = "<input type='text' id='textbox' /><button id='button'>Remove</button>";
this.listenTo(this,"all",function(){console.log("Event: "+arguments[0]);});
},
render : function() {
this.$el.html(this.html_text);
this.wrapper = new MyWrapper();
this.wrapper.set(this.$("#textbox"));
this.wrapper.get().val("placeholder");
return this;
},
onButton : function() {
// assume this gets .remove() called on subviews (if they existed)
this.trigger("cleanup");
this.remove();
}
});
var view = new MyView();
$("#content").append(view.render().el);
}
main();
但是,我不清楚如何使用Google Chrome的分析器来验证事实是否如此。 堆分析器快照中显示了一些巨大的事情,我不知道如何解码好/坏的东西。 到目前为止我看到的教程要么告诉我“使用快照分析器”,要么给我一个非常详细的关于整个分析器工作原理的说明。 是否有可能只使用探查器作为工具,还是我真的需要了解整个事情是如何设计的?
编辑:像这样的教程:
Gmail内存泄漏修复
使用DevTools
从我所看到的,代表一些更强大的材料。 然而,除了引入3快照技术的概念之外,我发现它们在实践知识(对于像我这样的初学者)方面提供的很少。 '使用DevTools'教程并不是一个真正的例子,所以它对事物的模糊和一般的概念性描述并不太有帮助。 至于'Gmail'的例子:
所以你发现了泄漏。 怎么办?
检查“配置”面板下半部分泄漏对象的保留路径
如果分配网站不容易推断(即事件监听):
通过JS控制台监视保留对象的构造函数以保存分配的堆栈轨迹
使用闭包? 启用适当的现有标志(即goog.events.Listener.ENABLE_MONITORING)在施工期间设置creationStack属性
阅读后我发现自己更加困惑,而不是更少。 而且,这只是告诉我要做,而不是如何去做。 从我的角度来看,所有的信息要么太模糊,要么只对已经了解过程的人有意义。
下面@Jonathan Naguin的答案提出了一些更具体的问题。
查找内存泄漏的良好工作流程是三种快照技术,Loreena Lee和Gmail团队首先使用这种技术来解决其内存问题。 一般来说,这些步骤是:
举个例子,我调整了代码来显示这个过程(你可以在这里找到它),延迟Backbone View的创建,直到Start按钮的点击事件。 现在:
现在您已准备好查找内存泄漏!
您会注意到几种不同颜色的节点。 红色节点没有从Javascript直接引用它们,但它们仍然活着,因为它们是分离的DOM树的一部分。 从Javascript引用的树中可能有一个节点(可能是一个闭包或变量),但巧合地阻止整个DOM树被垃圾收集。
然而,黄色节点确实有Javascript的直接引用。 在同一个分离的DOM树中查找黄色节点以查找来自Javascript的引用。 应该有从DOM窗口到元素的一系列属性。
在你的特定情况下,你可以看到一个标记为红色的HTML Div元素。 如果展开元素,您将看到由“缓存”功能引用的元素。
选择行并在您的控制台类型$ 0中,您将看到实际的功能和位置:
>$0
function cache( key, value ) {
// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
if ( keys.push( key += " " ) > Expr.cacheLength ) {
// Only keep the most recent entries
delete cache[ keys.shift() ];
}
return (cache[ key ] = value);
} jquery-2.0.2.js:1166
这是你的元素被引用的地方。 不幸的是,你可以做的事情不多,它是jQuery的内部机制。 但是,仅用于测试目的,请执行该功能并将方法更改为:
function cache( key, value ) {
return value;
}
现在,如果你重复这个过程,你将看不到任何红色节点:)
文档:
下面是一个关于jsfiddle内存分析的技巧:使用以下URL隔离您的jsfiddle结果,它会删除所有jsfiddle框架并仅加载结果。
http://jsfiddle.net/4QhR2/show/
在我阅读以下文档之前,我始终无法弄清楚如何使用Timeline和Profiler来追踪内存泄漏。 阅读标题为“对象分配跟踪器”的部分后,我可以使用“记录堆分配”工具,并跟踪一些分离的DOM节点。
我通过从jQuery事件绑定切换到使用Backbone事件委托来解决问题。 我的理解是,如果您调用View.remove()
,Backbone的新版本将自动为您解除绑定事件。 自己执行一些演示程序,它们会设置内存泄漏以供您识别。 如果在学习本文档后仍然没有得到答案,请随时提问。
https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling
基本上你需要看看堆快照中的对象数量。 如果两个快照之间的对象数量增加,并且已经丢弃了对象,则会发生内存泄漏。 我的建议是在代码中查找不会被分离的事件处理程序。
链接地址: http://www.djcxy.com/p/94545.html上一篇: Finding JavaScript memory leaks with Chrome
下一篇: dismiss mail controller view on pressing cancel button in action sheet