Ele*_*One 158 javascript memory-leaks google-chrome backbone.js
我创建了一个非常简单的测试用例,它创建了一个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();
Run Code Online (Sandbox Code Playgroud)
但是,我不清楚如何使用谷歌浏览器的分析器来验证这是事实.堆分析器快照上有很多东西出现,我不知道如何解码好/坏的东西.到目前为止我在其上看到的教程或者只是告诉我"使用快照分析器"或者给我一个关于整个分析器如何工作的非常详细的宣言.是否可以将探查器用作工具,或者我是否真的必须了解整个工具是如何设计的?
编辑:像这样的教程:
从我所看到的,代表一些更强大的材料.然而,除了引入3快照技术的概念之外,我发现它们在实践知识方面提供的很少(对于像我这样的初学者)."使用DevTools"教程并不适用于一个真实的例子,因此它对事物的模糊和一般概念性描述并没有太大帮助.至于'Gmail'示例:
所以你发现了泄漏.怎么办?
检查"配置文件"面板下半部分中泄漏对象的保留路径
如果分配站点不能轻易推断(即事件监听器):
通过JS控制台检测保留对象的构造函数,以保存用于分配的堆栈跟踪
使用关闭?启用适当的现有标志(即goog.events.Listener.ENABLE_MONITORING)以在构造期间设置creationStack属性
阅读之后我发现自己更加困惑,而不是更少.而且,它只是告诉我做事情,而不是如何去做.从我的角度来看,那里的所有信息要么太模糊,要么只对已经理解过程的人有意义.
其中一些更具体的问题已在@Jonathan Naguin的答案中提出.
Jon*_*uin 198
找到内存泄漏的良好工作流程是三种快照技术,Loreena Lee和Gmail团队首先使用它来解决一些内存问题.一般来说,步骤如下:
对于您的示例,我已经调整了代码以显示此过程(您可以在此处找到)延迟创建Backbone视图,直到"开始"按钮的单击事件.现在:
现在您已准备好发现内存泄漏!
你会注意到几种不同颜色的节点.红色节点没有从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
Run Code Online (Sandbox Code Playgroud)
这是您的元素被引用的位置.不幸的是,你没有太多可以做的,它是jQuery的内部机制.但是,仅用于测试目的,去功能并将方法更改为:
function cache( key, value ) {
return value;
}
Run Code Online (Sandbox Code Playgroud)
现在,如果你重复这个过程,你将看不到任何红色节点:)
文档:
这里有一个关于jsfiddle的内存分析的提示:使用以下URL来隔离你的jsfiddle结果,它删除所有的jsfiddle框架并只加载你的结果.
http://jsfiddle.net/4QhR2/show/
在阅读以下文档之前,我始终无法弄清楚如何使用Timeline和Profiler来跟踪内存泄漏.阅读标题为"对象分配跟踪器"的部分后,我能够使用"记录堆分配"工具,并跟踪一些分离的DOM节点.
我通过从jQuery事件绑定切换到使用Backbone事件委托来解决问题.我的理解是,如果你打电话,新版本的Backbone会自动为你解开事件View.remove().自己执行一些演示,它们设置有内存泄漏,供您识别.如果您在学习本文档后仍未获得问题,请随时在此处提问.
https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling
基本上,您需要查看堆快照中的对象数.如果两个快照之间的对象数量增加,并且您已经丢弃了对象,则会出现内存泄漏.我的建议是在代码中查找不会分离的事件处理程序.
| 归档时间: |
|
| 查看次数: |
63458 次 |
| 最近记录: |