Angular.js内存泄漏,何时应该开始担心

所以我有这个相当大的应用程序建立在角度,很多嵌套状态,很多指令,数据表和东西。

我们最近决定切换到完整的单页,而不是几个小的单个应用程序部分(说文章,人,仪表板以前都是一个小的单页面应用程序),所以我开始处理性能更多。 在Chrome中,你没有在视觉上注意到一个东西,另一方面我在Firefox上认为随着时间的推移会变慢。

所以我从三个快照技术开始,看看是什么。 但我不完全确定如何制作它。

图片 在此处输入图像描述

  • 快照大小每个快照的大小翻倍(第一个15mb,第二个67mb,第三个120mb),这是否意味着什么?
  • 例如,有很多红色的dom,4000个红色的div

现在我觉得那些红色的div,spans和anchor主要是我的错,我正在做一些不那么平常的东西来渲染那些数据表,使用我制作的这个指令,我也觉得有些堆对象是结果这些dom元素没有被正确删除。

这就是table指令的基本function

var rows = '
'; _.each(columns, function(column) { // pass cell as a string from $templateCache, instead of having which loaded correct templateUrl depending on what was passed via type attr var cellTemplate = $templateCache.get(column.type); rows += '
' + cellTemplate + '
'; }); rows += '
'; // el is from directive link function el.html(rows); $compile(el.contents())(scope);

我之所以这样做的原因是因为当我尝试对行和列使用嵌套的ng-repeat以及指令时,渲染时间太长,即使只有大约6列和50行。

所以我认为正在发生的是,这个表中的所有div都没有被正确删除,所以每次这个表指令加载时它们都会堆叠起来。

现在,即使我处理那个分离的dom树……那么所有其他的东西,我怎么知道我应该尝试和处理哪些,哪些是角度常见的并且不会真正影响性能?

//在plunker上编辑表格指令http://plnkr.co/edit/1fZi6mVn2jBIGF0Q2a40?p=preview

泄漏实际上是由另一个完全无害的查找指令引起的,该指令在表的标题中使用,除了创建“排序项”数组然后使用ng-repeat打印它之外什么也没做。更糟糕的是它没有引起通过我在该指令中所做的任何事情,但通过它的 replace: true …上帝知道为什么,我会尝试在plunker上重现它并报告github。

由于只是通过查看堆报告几乎不可能找到应用程序的哪个部分导致它,我继续删除应用程序的所有其他部分,但我怀疑它是导致它,然后我发现它不是’那一个,所以我继续阅读所有其他人。

一旦我发现了真正有问题的指令,我就做了同样的事情,不断删除部分代码,直到内部没有任何内容。

然后很明显它是指令的选项之一,然后我发现替换导致了它。

该指令不泄漏任何东西。 我分叉了你的plnkr,添加了更多的对象,如果它泄漏,它会引起注意,并添加了一个重新加载表的按钮。 它等待一秒钟,然后再次填充它。

节点被删除并重新创建。 尝试找到泄漏的步骤是:

  • 开始录制
  • 等2秒
  • 按下按钮
  • 等10秒钟
  • 停止录音

这样做了3次(所以你有相同的内存状态),你会看到正在使用相同的内存:

在此处输入图像描述

你可以检查分叉的plnkr

在此之后,我只能尝试猜测可能是什么问题。 我将根据我在这里发现的内容给你一些建议。

  • 检查指令,它们通常是原因。 frickingTable似乎没有做任何有害的事情,但其他习俗可能,即使他们不是你的,也只是发生了。
  • 如果正在使用某种“轮询”填充表,请在重新分配之前清空对象。 所以,如果你看到分叉的plnkr,你会看到我首先将itemsnull然后分配。 这应该是方式。 在plnkr中,我做了它是显而易见的(表重新填充)但是,我发现如果你不清理对象/数组,浏览器往往会以某种方式保留引用。 我清理了.length = 0数组和带有null对象,这使得对该对象的所有可能引用都准备好了GC,并且不会导致任何泄漏。 这听起来很傻,但我已经在Angular和Backbone中看到它,所以它必须是一个浏览器的东西。

如果没有看到更多代码,我真的无法想到任何其他东西。 希望这指向你正确的方向,泄漏是令人讨厌的至少。