angularjs内存消耗问题

ani*_*van 7 memory angularjs

最近我有机会构建一个新的Web应用程序,并考虑尝试Angular以便​​对它有一个很好的理解.所以是的,我对这个框架还是比较陌生的.

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

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

在此输入图像描述

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

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

在此输入图像描述

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

现在我已经检查了很多关于角度和内存消耗的问题,但是他们每个人都提到在$scope加载新视图时会删除任何视图.该DOM节点数量当然并不表示我这样一件事:/

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

  1. 避免在ng-repeat指令中调用任何函数.
  2. ng-modelng-repeat指令中没有使用双向绑定.

我在第二个屏幕中避免了这两个,然而,内存消耗正在通过屋顶.

我的问题可能似乎是另一个与角度有关的记忆相关问题,但我真的试图在此处得到某种关闭并且没有找到一个.

非常感谢任何有关这方面的帮助,因为我决定在门户的其余部分使用角度进展取决于解决这个问题.

谢谢阅读!

更新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');
                     });
                 }
            }
      };
});
Run Code Online (Sandbox Code Playgroud)

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

    $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
        $('#retailer').selectpicker('render');
    });
Run Code Online (Sandbox Code Playgroud)

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

更新2

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

在此输入图像描述

小智 3

我最近花了几天的时间发现与你类似的内存泄漏。这些并不是对你的问题的直接答案。您必须进行研究,但我可以为您提供一些查找泄漏的指示。

  1. 调试泄漏时,请勿在 Chrome 浏览器中使用除开发人员工具栏之外的任何其他插件。
  2. 时间线很适合找出泄漏,但要实际查看泄漏,请使用探查器选项卡。每次您拍摄堆快照时,它都会运行一次 GC,并为您提供是否有所改进的线索。
  3. 如果您发现内存泄漏(以 MB 为单位),则表明它来自 DOMElements。根据您提到的泄漏大小,我可以看出您的整个文档作为独立的 dom 元素挂起,因为页面中的一两个组件没有被释放,并且仍然作为附加的 dom 挂起。
  4. 删除第二页中的所有元素并进行切换以查看内存是否增加。如果是,则第一页有泄漏,否则对第二页执行相同的操作。
  5. 找到发生泄漏的页面后,从该页面删除所有组件并将它们一一添加,以查看泄漏何时返回。

希望这些步骤能在某种程度上帮助您。我还发现在指令中使用 $timeout 可能会导致泄漏,以防万一它有帮助。