1

This is what I'm doing. I have an ever growing array of pictures pictures for a photo slideshow. I display picture i as follows:

pictures[i]
   .fadeIn(500)
   .delay(5000)
   .fadeOut(500, function () {
        $(this).remove();
        delete this;
   });

Despite my attempts to flush the memory by using .remove() and delete, I am still having a memory leak. Am I doing something wrong?

Randomblue
  • 112,777
  • 145
  • 353
  • 547

1 Answers1

1

Update

As per the comments below, this was tested in Chrome and the browser seems to hold on to the memory from the images until the page is no longer actively rendered (reloaded, switched tab, etc.). Unfortunately, this holds true in Firefox and IE as well.

IE and Firefox had much better memory de-allocation (continually dropping memory as the page stayed open) but both still grew indefinitely. Upon switching tabs in both (by opening a new tab) the memory was almost immediately freed.

I haven't inspected your code thoroughly so I'm not sure if this problem can somehow be avoided (it doesn't appear so on first pass) though you should keep in mind that you are continually adding indicies to an ever-growing array that will continue to use more and more memory on its own. Perhaps it is the reference in the array that is sticking around which could be avoided if you came up with another way to implement the slideshow.

The reason why I'm guessing it might be this is from this discussion: garbage collection with node.js. The browser garbage collector needs to ensure that they are not reachable (which they always are, since the array is ever-growing). Thus you have to wait for the garbage collector to clean up the <img> values inside the indices to free the memory, and that doesn't necessarily happen right when you set them to null.


You'll need to pass your iterator i to your callback function. Then you'll be able to null the picture after it fades out and free the memory it was using. Just make sure you don't get caught in the common closure-iterator problem -- something like this should work:

pictures[i].fadeIn(500).delay(5000).fadeOut(500, (function(i) {
    pictures[i] = null;
})(i);
Community
  • 1
  • 1
skyline3000
  • 7,639
  • 2
  • 24
  • 33
  • How are you setting up the array of images? You mention it is ever-growing. Does it just go and fetch images all the time, or does it pre-load a couple and then get a new one after every fade. If your function just continually goes and adds new images to the array then you won't be able to free up memory as fast are you are using it (since there are timers in your animation effects). – skyline3000 Oct 19 '11 at 17:41
  • 1
    I don't know how you are creating your pictures array or how the elements are added into the DOM, but if pictures[i] is a reference to a DOM node, then you should pair this with removing the node as well. document.getElementById(picture's-parent-element).removeChild(pictures[i]); pictures[i] = null; If you still have a problem you'll need to post more of your code rather than just this snippet. – skyline3000 Oct 19 '11 at 19:00
  • I'm using jQuery to remove the node. Please see [here](http://jsfiddle.net/EhQ2Z/) for my complete code. It's not very long, and leaks like hell with Google Chrome. – Randomblue Oct 20 '11 at 08:41
  • What version of Chrome are you using? Have you tested other browsers? Unfortunately Chrome has had many well-documented memory leaks especially with images in the DOM. See here for an example: http://code.google.com/p/chromium/issues/detail?id=36142 . It seems to have something to do with how they are painting the screen... it's as if the memory is not de-allocated until the page is refreshed or you switch tabs. I was watching the memory grow gradually in the associated Google Chrome Renderer process to about 190MB. Then I switched tabs (to a New Tab) and it dropped back down to 70MB instantly – skyline3000 Oct 20 '11 at 16:25
  • The version of Chrome I am using is 15. Thanks skyline3000. That is helpful. – Randomblue Oct 20 '11 at 17:36