views:

60

answers:

1

Background

Back in May I reported an issue on WebKit regarding a memory retention issue. It looks as though the problem could be due to the Web Inspector itself, but I'm not convinced yet.

Problem

A problem surfaced whereby my JavaScript application implements a "Polling Consumer" pattern for obtaining data as it becomes available. The problem is that memory is being retained and grows throughout the day. The JavaScript logic goes like this:

  1. Get the data and call me back
  2. When I'm called back process the data and then perform step 1

Is this a reasonable way of implementing a polling consumer in JavaScript? Incidentally I'm using jQuery's ajax function which of course may have its own problems. In addition I'm using a jQuery proxy as the success handler so I would have thought that retention through scope should not be an issue. I have also observed the problem without using proxies. Some code:

FidsDataController.prototype.getFids = function() {
  var self = this;
  $.ajax({
...
    success: function(data) {
      // Do some processing
      // Call back in a short while...
      setTimeout($.proxy(self.getFids, self), 100);
    },
...
  });
);
+1  A: 

You have only one copy of getFids, which is good, but every time it gets called you are creating two new functions: one for the success handler and one from the $.proxy call. These two functions are not unique per call. Put them in reusable variables and you'll spare lots of extra function creation, which should lower your memory leak potential by a lot.

Example where we make proxied versions of each function once per object, in the constructor. Repeated calls will not generate more functions:

function FidsDataController() {
  // ...constructor...


  // Proxy these functions just once from the prototype
  this.getFids = $.proxy(this.getFids, this);
  this._getFids_success = $.proxy(this._getFids_success, this);
}

FidsDataController.prototype.getFids = function() {
  var self = this;
  $.ajax({
    success: this._getFids_success;
  });
};

FidsDataController.prototype._getFids_success = function(data) {
  // processing of data
  setTimeout(this.getFids, 100);
};
bcherry
I'm not sure I get what you're saying... can you provide an example in code? Also, I'm not trying to lower my memory leak; I'm trying to eliminate it!
Christopher Hunt
Sure, I'll edit with an example.
bcherry
Thanks for the example. As stated before though, I don't see my memory leak going away. I should also add that my problems occurred without using proxies too. Any other thoughts?
Christopher Hunt
Well, I don't think there's a lot you can do to eliminate leaks entirely in JavaScript. You could try moving the `100` and the object literal passed to the `$.ajax` function into static properties as well, if it might help. There's probably something else, though, that's not clear from this example.
bcherry
So let me then ask you another way, if you were to implement a polling consumer, would you do it in the way that I've done it?
Christopher Hunt
You should look into "Comet" techniques like long-poll and Web Sockets.
bcherry