28

I have the following issue. I am removing all references to a google maps instance including markers via the setMap(null) option via the following code:

destroyMaps = function () {
    leftMap = null;
    window.map = null;
    geocoder = null;
    for (var i=0; i<window.rightMarkers.length; i++) {
        window.rightMarkers[i].setMap(null);
        window.rightMarkers[i] = null;
    }
    window.rightMarkers = null;
    $("#map-canvas-right").remove();

    for (var i=0; i<window.leftMarkers.length; i++) {
        window.leftMarkers[i].setMap(null);
        window.leftMarkers[i] = null;
    }
    window.leftMarkers = null;
    $("#map-canvas-left").remove();

}

The only things that reference leftMap or window.map in my whole code is:

For window.map

var marker = new google.maps.Marker({
                    position: myLatlng,
                    map: window.map,
                    icon: window.pins[keyword_category.category_name],
                    shadow: window.pins["Shadow"],

                    title:job.job_title
});
marker.job_type =  keyword_category.category_name;
window.rightMarkers.push(marker);

For leftMap

var marker = new google.maps.Marker({
                position: myLatlng,
                map: leftMap,
                icon: window.pins[keyword_category.category_name],
                shadow: window.pins["Shadow"],

                title:job.job_title
 });
 window.leftMarkers.push(marker);

However in my detached DOM tree, when comparing before the maps were created / after they were destroyed, remains the google maps tiles:

enter image description here

(Right click - open image to see full size)

What can I do to find out what's causing this DOM leak?

Tomas
  • 57,621
  • 49
  • 238
  • 373
rickyduck
  • 4,030
  • 14
  • 58
  • 93
  • Do you have any event handlers attached to map, markers...? – Anto Jurković Jan 15 '14 at 20:05
  • 1
    @AntoJurković Nope, none at all. I can link to my code if needs be, however there's a lot of non-related code inbetween – rickyduck Jan 16 '14 at 09:55
  • maybe GC didn't managed to fire. Can you please make another test, with Timeline chrome dev tools tab with using 'Collect garbage' button (in the bottom) – Vlad Nikitin Jan 17 '14 at 16:23
  • @VladNikitin - I have already attempted a forced "garbage collection" via the Timeline tab but to no avail, implying somewhere there is a reference. – rickyduck Jan 17 '14 at 16:34
  • http://jsfiddle.net/54Lf7/ contains the whole code which controls the frontend. – rickyduck Jan 17 '14 at 16:34
  • your JSFIDDLE example does not run. It would be very useful if you create as simple as possible, complete, minimal example demonstrating the problem. Otherwise, we have nothing to debug and it will be hard to impossible to answer your question. – Tomas Jan 17 '14 at 17:01
  • @Tomas - unfortunately this is impossible on jsfiddle. I have deployed it as a meteor bundle to http://pytec.meteor.com/frontend/map/ which has the map and http://pytec.meteor.com/frontend/charts/ - however it always says the site is down, despite running on my local machine – rickyduck Jan 17 '14 at 17:12
  • @rickyduck, I added another answer. I think you unset marker for map, but did not delete marker instance. marker DOM might be related to marker instance. – allenhwkim Jan 21 '14 at 15:45

1 Answers1

32

This is a known issue in Google Maps API v3 - even pure creation and destruction of google.maps object (no marker creation) results in memory leak. See Issue 3803: Bug: Destroying Google Map Instance Never Frees Memory.

They reproduce the issue by creating a simple loop that creates and destroys the google.maps object. See

http://jsfiddle.net/KWf4r/

After pressing start, you will observe your browser to grow in memory until you press stop.

The issue is not fixed and there doesn't seem to be an official workaround available. There is certainly a way, but it's not a clean workaround that apparently might stop working in next release of google maps api - citing the discussion:

I've actually managed to find a semi-workable fix by manually destroying a lot of the elements that google maps creates (and removing listeners). However, I am using a lot of undocumented things to do this (I had to check in the chrome inspector to see what to try to remove), so this doesn't seem the right way to go.

Tomas
  • 57,621
  • 49
  • 238
  • 373
  • another workaround is A) Reuse the same maps instance B) Move over to Bing? – rickyduck Jan 20 '14 at 10:32
  • 3
    Reusing the same maps instance worked for me. I acheived this by grabbing the element: `window.$leftMap = $(".leftMap");` in jQuery, and reusing it by appending it to the parent element when it came back round: `$("#map-canvas-left").append(window.$leftMap);` – rickyduck Jan 20 '14 at 16:36
  • 1
    I will leave the bounty for a couple of days to see if a solution comes around for actually destroying all of the instance, and if not I will award the bounty to this answer. – rickyduck Jan 20 '14 at 16:37
  • rickyduck, your experiment with reusing same maps instance is interesting! But I thought it is not a solution to your problem - I thought you need to destroy google maps and free the all the memory it uses. If you don't need to reuse the maps, you still have leak. – Tomas Jan 22 '14 at 12:10
  • it is a solution to my problem in the sense that it eradicated my memory leak issues for a project that was time critical. I was destroying the map and re-initiating it as there was some work on load that needed to be done. I have changed this code around now and made it so the instance was reusable and my code still worked. However - you are correct that it doesn't fix the memory leak. I would rather you got the bounty for solving my issue, though, than it disappearing because it doesn't fix the memory leak. – rickyduck Jan 22 '14 at 13:14
  • @rickyduck yes that would be ideal but it requires to fix google's code, which we unfortunatelly can't. Any other fix will just be a dirty workaround - as I cited in the answer. Once I did [such a dirty thing](http://stackoverflow.com/a/8361698) because there was no other solution, and it stopped working later. I think all we can do is to share and make as many people as possible to **star the issue** by [clicking the star in the title](http://code.google.com/p/gmaps-api-issues/issues/detail?id=3803) so that google prioritizes it. – Tomas Jan 22 '14 at 13:58
  • @rickyduck PS: glad reuse works for you, but agree it's not a real solution of the problem. Be careful though with the reusing. Its unintended and undocumented use of the library which might work now but can break any time, because possibly the library assumes it starts on a fresh instance, and if there is some trash left... you know :) – Tomas Jan 22 '14 at 14:00
  • wasn't aware of the starring, so I have done. I may update the question to add it to make it more prominent. I think in my case it's not too much of an issue because all I'm doing is going round in a circle back to the original page, and reusing the DOM element and instance in exactly the same place as it was before. For others, however, this is not a viable solution as they will be using the maps instance for something seperate. – rickyduck Jan 22 '14 at 14:06