3

I implemented a web application and monitored the performance with the google developer tools. I notice that the listeners keep increasing and so is the heap.

enter image description here

The part where the listeners are increasing looks something like this

let ival = $interval(function () {
    $http.get('someurl') // this call is actually done through a service, don't know if that matters
}, 1000)

I would understand if the heap grows because of some data not beeing collected by the garbage collector but I don't understand why the listeners are increasing?

Here is a reproducable, minimal example:

The index.html file:

<!doctype html>
<html ng-app="exampleModule">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
    <script src="script.js"></script>
  </head>
  <body>
    <div ng-controller="someController">
    </div>
  </body>
</html>

And the script.js file:

angular.module("exampleModule", [])
  .controller("someController", [ "$http", "$interval", function ($http, $interval) {

    $interval(function () {
      $http.get('script.js')
    }, 1000)

  }])

The results when you watch the performance are the same as in the picture above. You should use a simple webserver in order to make the GET request.

CDspace
  • 2,639
  • 18
  • 30
  • 36
Stefan
  • 721
  • 1
  • 10
  • 24
  • Do you call `$interval.cancel(ival);` somewhere, or stop that interval somehow else? Or is a new interval created over and over again, without stopping the old one? – t.niese Oct 11 '17 at 19:32
  • $interval.cancel(ival) will be called once the activity will be destroyed. The interval is beeing created when the activity is created. – Stefan Oct 11 '17 at 19:47
  • Does it work similarly for you when the app consists only of a snippet you've shown? If it doesn't, you need to provide http://stackoverflow.com/help/mcve that replicates your problem. It can be virtually everything. – Estus Flask Oct 11 '17 at 20:35

2 Answers2

15

According to this issue, more specifically this comment, it's caused by Chrome not garbage collecting listeners during recording of the performance timeline.

robertklep
  • 198,204
  • 35
  • 394
  • 381
  • 1
    That's it. I executed garbage collection during the recording and the heap perfomance is fine. I don't understand why the gc is not collecting listeners during recording. Thanks for the answer. – Stefan Oct 14 '17 at 13:44
0

Your get request probably lasts more than 1 second. But you call it every 1 second. So one request starts before other one finishes, and they pile up, eventually getting slower.

I suggest, don't do a request if the previous one isn't finished:

let previousOneOngoing = false;
let ival = $interval(function () {
    if(previousOneOngoing) return;
    previousOneOngoing = true;
    $http.get('someurl')
        .then(function() { previousOneOngoing = false; })
}, 1000)
Gokhan Kurt
  • 8,239
  • 1
  • 27
  • 51
  • The requests only last like 3ms. I implemented it with $timeout and set a new timeout when the old one was finished. Same result. I just used a simple XMLHttpRequest in the interval and the the heap did not grow. So I think the $http is doing something it shouldn't – Stefan Oct 14 '17 at 13:02
  • @Stefan Sorry for misunderstanding. See the answer by robertklep. – Gokhan Kurt Oct 14 '17 at 13:22