Why isn't nodes and listeners being cleaned up

2019-09-15 10:21发布

I'm investigating the cause of a memory leak having to do with the nodes count, but I'm just getting confused when I look at what angular is doing, because the results are not consistent enough to draw a clear line of what is happening.

I've created a really simple app, it has 1 controller and 2 views. Each view use the same 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'});
}]);

I then record a timeline in the Chrome dev tools, alternating between switching between the views quickly and then every other second, as you can see clearly in the graph.

This is the results:

terminal timeline

As you can see after the first period of switching quickly, the nodes count drop massively, then I start switching views more slowly and then fast again. This time after switching more quickly the drop of nodes count is not even close to that of the first drop, as well as the nodes continuing to go up after that.

There are 2 things here that are off to me:

  • 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?

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

To me this seems like something can't keep up with cleaning up after itself when switching between the views. Or something isn't being cleaned up at all, which is odd since there are no listeners that would require manual cleanup.

Can anyone make any sense out of these test results?

1条回答
狗以群分
2楼-- · 2019-09-15 10:54

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?

The memory does not go down immediately since you can't really control when the garbage collection will occur. Usually, the browser only cleans up the memory when it needs to allocate more space and it needs to free up some room first.

That is why, for debugging purposes, you have access to the "Collect garbage" button in the DevToolbar (enter image description here). You should press this button at the beggining and end of every recording, and in your case, you could even press it everytime you finished switching the pages. This way you will have the guarantee that you are looking at the used memory instead of the occupied memory.

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

This is likely because of the same cause.


I profiled your code and I got the following timeline after manually triggering the garbage collection:

enter image description here

As you can see, it seems like all the event listeners and nodes were correctly cleaned up.

If, in spite of this, you are still experiencing lag on a slow machine, it is likely this happens because they run out of memory faster and need to perform garbage collection more often.

As mentioned in the 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.

It's not really clear if this is the particular problem your app is facing though, so you would need to investigate further. It's likely something more complex is going on in your app than in this simple example.

I found the Chrome DevTools CPU throttling feature very useful in getting the same slowness that my users were having with the application. Also, this talk by the Gmail team was great at explaining how to track down these issues and showing the relation between memory usage and performance of an app.

查看更多
登录 后发表回答