javascript - 为什么节点和监听器没有以一致的方式正确清理?

标签 javascript angularjs memory memory-leaks google-chrome-devtools

我正在调查与节点计数有关的内存泄漏的原因,但是当我查看 Angular 正在执行的操作时,我只是感到困惑,因为结果不够一致,无法划出一条清晰的界限发生了什么。

我创建了一个非常简单的应用程序,它有 1 个 Controller 和 2 个 View 。每个 View 使用相同的 Controller :

core.controller('CoreCtrl', [function() {

  var core = this;

  core.helloWorld = function() {
    console.log('hello world');
  };
}]);

core.config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/test1', {
      template: '<a href="#/test2" ng-click="core.helloWorld()">Go to test 2</a>',
      controller: 'CoreCtrl',
      controllerAs: 'core'
    })
    .when('/test2', {
      template: '<a href="#/test1" ng-click="core.helloWorld()">Go to test 1</a>',
      controller: 'CoreCtrl',
      controllerAs: 'core'
    })
    .otherwise({redirectTo: '/test1'});
}]);

然后,我在 Chrome 开发工具中记录一条时间线,在 View 之间快速切换和每隔一秒切换一次,正如您在图中可以清楚地看到的那样。

这是结果:

terminal timeline

正如您所看到的,在第一个快速切换周期之后,节点数量大幅下降,然后我开始更慢地切换 View ,然后再次快速切换。这次切换速度更快后,节点数的下降甚至不接近第一次下降的数量,并且此后节点继续上升。

这里有两件事对我来说很重要:

  • 为什么切换 View 后节点数和监听器数一直在上升,一段时间后才下降?因为每个 View 切换都应该清理节点和监听器,所以这不应该更像是锯齿模式吗? - _ - _ - _ - _-

  • 为什么第二个水滴没有第一个水滴那么大?

对我来说,在 View 之间切换时,这似乎无法跟上自身的清理工作。或者有些东西根本没有被清理,这很奇怪,因为没有监听器需要手动清理。

有人能理解这些测试结果吗?

最佳答案

Why does the nodes and listeners count keep going up after you switch view, only dropping after a certain period? Shouldn't this be more of a sawtooth pattern, - _ - _ - _ - _- since each view switch should do a cleanup of the nodes and listeners?

内存不会立即下降,因为您无法真正控制垃圾收集何时发生。通常,浏览器只有在需要分配更多空间时才会清理内存,并且需要先释放一些空间。

这就是为什么出于调试目的,您可以访问 DevToolbar 中的“收集垃圾”按钮 ( enter image description here )。您应该在每次录音的开始和结束时按此按钮,在您的情况下,您甚至可以在每次完成页面切换时按它。这样您就可以保证您看到的是已用内存,而不是已占用内存。

Why isn't the second drop as big as the first one?

这可能是由于相同的原因。

<小时/>

我分析了您的代码,并在手动触发垃圾收集后得到了以下时间表:

enter image description here

如您所见,似乎所有事件监听器和节点都已正确清理。

尽管如此,如果您在速度较慢的计算机上仍然遇到延迟,很可能会发生这种情况,因为它们更快地耗尽内存,并且需要更频繁地执行垃圾收集。

DevTools docs 中所述:

A page’s performance is delayed or appears to pause frequently. This is possibly a symptom of frequent garbage collections. Garbage collection is when the browser reclaims memory. The browser decides when this happens. During collections, all script execution is paused. So if the browser is garbage collecting a lot, script execution is going to get paused a lot.

目前尚不清楚这是否是您的应用面临的特定问题,因此您需要进一步调查。您的应用程序中可能发生的事情比这个简单的示例更复杂。

我找到了 Chrome DevTools CPU throttling该功能对于获得与我的用户使用该应用程序相同的缓慢程度非常有用。另外,this talk Gmail 团队的作者非常擅长解释如何追踪这些问题并显示内存使用情况与应用程序性能之间的关系。

关于javascript - 为什么节点和监听器没有以一致的方式正确清理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39587674/

相关文章:

javascript - 如何查找用户是否单击了浏览器后退按钮或刷新按钮

javascript - 在 angular-ui 模式中显示谷歌地图?

python - 大pandas DataFrames上的外部合并导致MemoryError——如何与pandas进行 "big data"合并?

java - 大 XML 文件和 OutOfMemoryError

javascript - 使用 float 新添加的数据点的平滑动画

javascript - 使用 AngularJS 反转滚动方向

javascript - 默认水平滚动的表格

javascript - Angular 自定义指令范围未按预期更新

javascript - Adapt-strap/Angular 动态表柱

caching - Nginx 内容缓存导致 Docker 内存峰值