angularjs内存消耗问题

时间:2014-01-22 12:12:58

标签: angularjs memory

最近我有机会构建一个新的Web应用程序,并考虑尝试使用Angular来更好地理解它。所以,是的,我已经相当新这个框架了。

在了解了框架的细微差别之后,我发现它的使用起来非常简单。关于我的经验的一切都很棒,直到用户开始报告应用程序的完全滞后性能。

应用程序非常简单 - 它有2个屏幕。一个显示交易列表,另一个显示交易信息 - 用户可以添加/编辑交易信息 - 第二个页面是一个简单的表单,期望用户输入交易相关信息。它看起来像这样:

enter image description here

使用ng-repeat呈现概述的部分。零售商列表有大约530个条目,而品牌列表有大约400个条目。

经过一些分析后,我发现访问第二个窗体屏幕会继续增加浏览器的内存消耗。第一个屏幕没有任何这样的效果。我只是在第一个屏幕和第二个窗体屏幕之间切换,发现每次加载这个屏幕时,内存消耗量会飙升50-75 MB。最终,浏览器会冻结。以下是内存配置文件的外观:

enter image description here

正如您所看到的,消费量持续上升,并且没有任何GC的迹象!节点计数和内存跟踪中的每个峰值都对应于访问第二个基于表单的屏幕。

现在我已经检查了很多关于角度和内存消耗的问题,但是他们每个人都提到在加载新视图时,任何视图的$scope都会被删除。 DOM节点计数对我来说当然不能表明这样的事情:/

我还发现了与ng-repeat的使用相关的两个要点:

  1. 避免在ng-repeat指令中调用任何函数。
  2. ng-model指令中使用ng-repeat进行双向绑定。
  3. 我在第二个屏幕上都避免了这两个问题,然而,内存消耗却在不断增加。

    我的问题可能似乎是另一个内存相关的问题w.r.t angular,但我真的试图在此处获得某种关闭并且找不到它。

    非常感谢对此的任何帮助,因为我决定在门户网站其余部分使用角度进展取决于解决此问题。

    感谢阅读!

    更新1

    根据Ilan的建议,让我补充一点,我使用2个插件来渲染下拉列表并实现日期选择器。

    对于下拉列表,我使用Bootstrap-select,对于日期选择器,我使用Bootstrap-datepicker

    要使bootstrap-select正常工作,我必须编写一个自定义指令,该指令在$last事件ng-repeat上触发广播。它看起来像这样:

    .directive('onFinishRender', function($timeout) {
        return {
            restrict : 'A',
                link : function(scope, element, attr) {
                    if (scope.$last === true) {
                        $timeout(function() {
                            scope.$emit('ngRepeatFinished');
                         });
                     }
                }
          };
    });
    

    然后在控制器中,我依靠这个事件来调用下拉插件的渲染:

        $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
            $('#retailer').selectpicker('render');
        });
    

    对于bootstrap-datepicker,我不需要做这么精细的事情,因为我只需要使用JS包装日期输入字段。

    更新2

    关闭插件后,内存消耗急剧下降。但是,泄漏问题仍然存在。早些时候,每当表单视图加载时,内存将飙升50-60 MB。关闭插件后,它会飙升25-35 MB。但是正如你在下面看到的那样,内存消耗不断增加。

    enter image description here

1 个答案:

答案 0 :(得分:3)

我最近花了几天时间才发现与你的内存泄漏类似的内存泄漏。这些都不是你问题的直接答案。你将不得不做研究,但我可以给你一些指向找到泄漏的指示。

  1. 调试泄漏时,除了开发人员工具栏外,不要在Chrome浏览器中使用任何其他插件。
  2. 时间轴很好地确定存在泄漏,但要实际看到泄漏,请使用分析器选项卡。每次拍摄堆快照时它都会运行GC,如果你改进了,它会给你一个线索。
  3. 如果您发现MB中的内存泄漏比来自DOMElements的内存泄漏。根据您提到的泄漏大小,我可以判断您的整个文档是作为分离的dom元素挂起的,因为页面中的一个或两个组件未被释放,并且仍然作为附加的dom挂起。
  4. 从第二页中删除所有元素并进行切换以查看内存是否在增加。如果是这样,第一页有泄漏,否则与第二页相同。
  5. 找到泄漏的页面后,从该页面中删除所有组件并逐个添加,以查看泄漏何时返回。
  6. 希望这些步骤能够以某种方式帮助您。另外我发现在指令中使用$ timeout会导致泄漏,以防它有所帮助。