26

All versions of IE (including 10) appear to hold on to a significant amount of memory allocated by iframes until window.top.unload occurs. This creates quite the challenge for long-lived pages that may create a number of iframes throughout their lifetime. A simplified example of the problem can be found here:

http://pastebin.com/FmZ7iMHB

That example uses a Wikipedia page for the iframe to magnify the problem, but even a simple page with a single image will leak.

In a nutshell, after you destroy an iframe in IE you get some but not all of the memory back the next time a page triggers a garbage collection (typically about 25% of the memory used by the iframe gets stuck in limbo). Refreshing or navigating to a new page (window.top.unload) will free up most or all of the remaining memory.

This particular leak is not detectable in tools like sIEve and Microsoft's JS Memory Leak Detector. I've read everything I can find about leaky iframes in IE, but have had no luck with the solutions I've come across.

Does anyone know a solution or workaround to this problem? The only mitigation strategy I have is to do as much cleanup as you can from within the iframe before the parent page destroys it, but that doesn't help when you don't control the page being framed in.

Josh
  • 1,277
  • 2
  • 14
  • 16
  • Could it just be caching? Many browsers keep images etc. in memory so they won't have to redownload them next time they are needed. If there was a real memory leak, Microsoft would have fixed it by now. – Lambda Fairy Dec 06 '11 at 23:08
  • 1
    I believe technically this is a ["pseudo-leak"](http://outofhanwell.com/ieleak/index.php?title=Fixing_Leaks#Pseudo-Leaks), meaning that the lost memory is reclaimed when the parent page unloads and is not actually lost forever. However, as the link above mentions this is still a problem for long-lived pages (think Pandora or web-based monitoring tools, where you may leave the page open for hours). Unfortunately the solution offered does not have an effect in this case. – Josh Dec 07 '11 at 01:08
  • 2
    I don't think that caching is a factor (I could certainly be wrong though), since disabling the browser cache via the F12 Developer Tools does not appear to have an effect, and loading a simple page with the same image repeatedly will leak. – Josh Dec 07 '11 at 01:14
  • Josh, did you have any news under this subject? – rafa.ferreira Aug 09 '13 at 21:00
  • @Castanho I don't think this is fixable, but it can definitely be mitigated. If you have long-lived pages and lots of IE visitors, you should do everything you can to avoid iframes that load large files. The typical culprit when this is a problem is rotating ads, which create iframes with images or flash content over and over, leaking a small amount of memory each time that slowly adds up. – Josh Aug 19 '13 at 00:26

4 Answers4

8

I put together a jQuery plugin for cleaning iframes that prevents memory leaks in some cases:

(function($) {
    $.fn.purgeFrame = function() {
        var deferred;

        if ($.browser.msie && parseFloat($.browser.version, 10) < 9) {
            deferred = purge(this);
        } else {
            this.remove();
            deferred = $.Deferred();
            deferred.resolve();
        }

        return deferred;
    };

    function purge($frame) {
        var sem = $frame.length
          , deferred = $.Deferred();

        $frame.load(function() {
            var frame = this;
            frame.contentWindow.document.innerHTML = '';

            sem -= 1;
            if (sem <= 0) {
                $frame.remove();
                deferred.resolve();
            }
        });
        $frame.attr('src', 'about:blank');

        if ($frame.length === 0) {
            deferred.resolve();
        }

        return deferred.promise();
    }
})(jQuery);

This code handles cross-origin frames by updating the frame src to "about:blank" before cleaning its content. To use the plugin, call $frame.purgeFrame() where you would otherwise call $frame.remove().

As Josh points out, iframes that display an image seem correlated with memory leaks. For example, creating iframes pointing to google.com will produce a memory leak in IE7 and IE8. Using the plugin above prevents those leaks.

Unfortunately that plugin is not effective in all cases. It does not seem to help much with iframes pointed at //en.wikipedia.org/wiki/Memory_leak.

The code that I used for testing memory leaks and for testing the above plugin is at https://gist.github.com/3125807

As Josh says, the memory leaks are actually pseudo-leaks in IE8. However in IE7 memory is not reclaimed, even when the parent window unloads.

Jesse Hallett
  • 1,857
  • 17
  • 26
2

In IE 11, just setting iframe.src = 'about:blank' seems to fix this. Otherwise, you can watch the memory grow forever in the F12 Memory tab, even if you're removing iframes from the DOM and letting them be garbage collected. If you blank the iframes first, you see the memory go up and down as you'd expect.

Jay G
  • 167
  • 1
  • 6
0

Have a try with this:

collectGarbageForIframe: function() {
  var $iframes = $("*[tag='iframe']");
  $iframes.each(function() {
    var $target = $(this);
    if($target.length>0) {
      $target[0].src = "about:blank";
      $target[0].contentWindow.document.write('');
      $target[0].contentWindow.close();
      $target.remove();
      if( typeof CollectGarbage == "function") {
        CollectGarbage();
      }
    }
  });
}
Liber
  • 422
  • 4
  • 12
0

You are missing one important step: After setting the src to 'about:blank', you need to listen to the load of 'about:blank', and only then remove your iFrame.

Megi Ben Nun
  • 405
  • 3
  • 6
  • 20