在使用ng-repeat AngularJS构建大型表之后,垃圾收集在Internet Explorer中需要很长时间

时间:2015-02-10 23:55:41

标签: javascript jquery angularjs internet-explorer garbage-collection

我正在使用AngularJS(1.2.26)的ng-repeat指令构建一个大表(3,000多行)。数据是一个非常简单的时间和温度数组[[time, temperature], [time, temperature], ...]

这是数据在表格中的显示方式(使用Slim templating):

  table.table.table-bordered
    thead
      tr
        th.time.first-child= t('Time')
        th.temperature.sensor
    tbody
      tr[bindonce ng-repeat="item in readings"]
        td.datetime
          span.date bo-text="formatDate(item.time)"
          span.time bo-html="formatTime(item.time)"
        td bo-text="item.reading.temperature | number: 2" 

如您所见,我们正在使用bind once库来减少角度观察者的数量。这是一份报告,因此我们不需要维护数据绑定。

在Chrome或Firefox上加载数据并呈现报告大约需要4秒钟,在Internet Explorer(11)上大约需要8秒钟。但是,在Internet Explorer上构建表后,浏览器最多需要两分钟才能执行垃圾收集(根据UI响应性选项卡)。

我需要更多"声誉"发布图片,所以我会尽力描述正在发生的事情。

整个表格渲染过程是xhr.onreadystatechange事件监听器(后来从1.3中的角度移除)的结果。使用appendChild() - >将每行和每个范围添加到表格中来自jQuery的insertBefore()函数或来自浏览器的innerHTML函数。这些发生了数千次,占我之前提到的~8秒。完成这些操作后,会立即进行几行垃圾收集,总共需要60秒以上。

如果没有输出图片,这是在最后appendChild()之后开始执行的时间列表,后面是总执行时间(窗口中条形图的长度)。

  1. 0.24 s,0.0065 ms
  2. 0.36 s,13.83 ms
  3. 0.85 s,0.31 ms
  4. 10 s,0.0042 ms
  5. 57 s,25.54 ms
  6. 60 s,0.048 ms
  7. 然后,在剩余的过程进行之前还有大约10秒的另一个间隙。

    我不明白这里发生了什么,因为每个垃圾收集都很短,但它们之间的差距很大。我对浏览器中的垃圾收集知之甚少,所以我的理解会受到阻碍。这不是在Chrome或Firefox中发生的。

    我已经关注了有关分析内存分析的各种指南。我不相信有内存泄漏。同样,由于我的声誉,我无法添加更多链接,但我跟着Chrome一个名为" JavaScript Memory Profiling"和IE标题为“#34;提高用户界面响应能力"。

    还有另一部分,我不确定它是否相关,但我会在这里提及它,以防万一。在此延迟期间运行性能分析会话时,IE表示延迟是在AngularJS https://github.com/angular/angular.js/blob/master/src/ng/raf.js#L15的requestAnimationFrame $$RAFProvider函数期间。这可能与AngularJS触发"输入"通过ng-repeat添加的每一行的事件。到目前为止,我一直在尝试禁用该动画事件。

    非常感谢任何建议或疑难解答提示。具体来说,如果我可以在垃圾收集上添加一个断点来查看发生了什么,那就太棒了,但我不认为我能做到这一点。

2 个答案:

答案 0 :(得分:3)

经过多次调查,我认为我弄清楚问题是什么,或者至少是一个潜在的问题。

我正在渲染的表有两列 - 时间和温度。时间列有两个<span>个元素。因此,对于每一行,Angular都标记了&#34;输入&#34;动画,因为它为ng-repeat的每个元素。作为Angular动画过程的一部分,Angular通过$RAFProvider从浏览器请求动画帧。当我在Internet Explorer中分析该进程并查看调用堆栈时,这是一个巨大的延迟。我原本以为这不是问题所在,但经过大量的故障排除后,我开始认为Internet Explorer requestAnimationFrame方法几乎不能像Chrome或Firefox一样快速处理~9000个调用。

为了解决这个问题,我选择实施ngInfiniteScroll并且它运作良好。如果用户真的想要完整报告,我们将通过不同的代码路径生成完整的3,000行报告。

答案 1 :(得分:0)

对于ng-repeat,angular将为重复进行双向绑定的每个项目创建一个范围。但是在您的代码中,没有必要,您只需显示数据。

如果您使用的是angularjs 1.3.x以上,则可以使用binging-once功能,然后不会创建这些范围。

我不熟悉那个模板。但你在TR中使用'bindonce',如果在angularjs中是'bindonce',我认为你应该使用1.3.x版本。

另一个问题是:

span.date bo-text="formatDate(item.time)"

您使用数据格式的函数。如上所述,你应该使用'bind-once'。如果你使用js,那就是:

<span>{{::formatDate(item.time)}}</span>

为绑定添加'::'一次。

如果不添加bind一次,当您滚动表格时,同一项目的格式化功能将被多次调用。因此,对于格式,您应该使用日期过滤器,如:

<span>{{item.time | date: 'yyyy/MM/DD'}}</span>