使用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团队首先使用这种技术来解决其内存问题。 一般来说,这些步骤是:

  • 采取堆快照。
  • 做东西。
  • 拍另一个堆快照。
  • 重复相同的东西。
  • 拍另一个堆快照。
  • 在快照3的“摘要”视图中筛选在快照1和快照2之间分配的对象。
  • 举个例子,我调整了代码来显示这个过程(你可以在这里找到它),延迟Backbone View的创建,直到Start按钮的点击事件。 现在:

  • 运行HTML(使用此地址在本地保存)并拍摄快照。
  • 点击开始创建视图。
  • 拍另一张快照。
  • 点击移除。
  • 拍另一张快照。
  • 在快照3的“摘要”视图中筛选在快照1和快照2之间分配的对象。
  • 现在您已准备好查找内存泄漏!

    您会注意到几种不同颜色的节点。 红色节点没有从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;
    }
    

    现在,如果你重复这个过程,你将看不到任何红色节点:)

    文档:

  • 消除Gmail中的内存泄漏。
  • 在Chrome DevTools中简化JavaScript内存分析。

  • 下面是一个关于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