繁体   English   中英

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

[英]Garbage collection takes a very long time in Internet Explorer after building a large table with ng-repeat AngularJS

我正在使用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" 

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

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

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

整个表呈现过程是xhr.onreadystatechange事件侦听器的结果(此后已从1.3中的angular中删除)。 每行和跨度都使用jQuery的appendChild() -> insertBefore()函数或浏览器的innerHTML函数添加到表中。 这些事件发生了数千次,占了我之前提到的〜8秒。 一旦完成这些操作,将立即进行几行垃圾收集,总共需要60秒钟以上的时间。

在没有输出图片的情况下,这是最后一个appendChild()之后开始执行的时间的列表,然后是总执行时间(窗口中条的长度)。

  1. 0.24 s,0.0065毫秒
  2. 0.36 s,13.83毫秒
  3. 0.85 s,0.31毫秒
  4. 10 s,0.0042毫秒
  5. 57 s,25.54 ms
  6. 60 s,0.048毫秒

然后,在其余的过程进行之前,还有大约10 s的间隔。

我不明白这里发生了什么,因为每个垃圾收集都很短,但是它们之间的间隔很长。 我对浏览器中的垃圾收集了解不多,因此妨碍了我的理解。 Chrome或Firefox中不会发生这种情况。

我遵循了有关分析内存分析的各种指南。 我不相信内存泄漏。 同样,由于声誉原因,我无法添加更多链接,但是我跟随的是Chrome浏览器,标题为“ JavaScript Memory Profiling”,而IE浏览器的标题为“ Improving UI Responsiveness”。

还有一点我不确定是否相关,但是如果有必要,我会在这里提及。 当您在此延迟期间运行性能分析会话时,IE表示延迟是在AngularJS $$RAFProvider的requestAnimationFrame https://github.com/angular/angular.js/blob/master/src/ng/raf.js#L15函数期间$$RAFProvider 这可能与AngularJS为通过ng-repeat添加的每一行触发一个“ enter”事件有关。 到目前为止,我一直在尝试禁用该动画事件而没有运气。

任何建议或故障排除技巧将不胜感激。 具体来说,如果我可以在垃圾回收上添加一个断点以查看发生了什么,那将是很好的,但是我认为我不能做到这一点。

经过大量调查,我认为我找出了问题所在,或者至少是一个潜在问题。

我绘制的表有两列-时间和温度。 时间列具有两个<span>元素。 因此,对于每一行,Angular都为ng-repeat每个元素标记“输入”动画的元素。 作为Angular动画过程的一部分,Angular通过$ RAFProvider从浏览器请求动画帧。 当我在Internet Explorer中分析该过程并查看调用堆栈时,这就是巨大的延迟所在。 我最初以为这不是问题,但是经过大量的故障排除后,我开始认为Internet Explorer的requestAnimationFrame方法无法像Chrome或Firefox一样快地处理约9000个调用。

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

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

如果您使用的是angularjs 1.3.x以上版本,则可以使用binging-once功能,那么将不会创建这些作用域。

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

另一个问题是:

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

您使用函数的数据格式。 并且作为上述问题,您应该使用“一次绑定”。 如果使用js,则为:

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

添加“ ::”一次绑定。

如果您一次不添加绑定,则在表格上滚动时,同一项目的格式函数将被调用多次。 因此,对于格式,您应该使用日期过滤器,例如:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM