Утечка памяти в Javascript с помощью метода Google Maps Map.panTo () - PullRequest
0 голосов
/ 16 сентября 2011

Я сталкивался с ошибками Javascript Out of Memory в веб-приложении, которое загружает карту Google и непрерывно перемещается из одной точки в другую.Требуется около половины дня, прежде чем у него не останется памяти, но мне бы очень хотелось, чтобы он длился гораздо дольше.Я обнаружил, что утечка памяти происходит при использовании метода map.panTo, хотя я очень подозреваю, что это может быть способ, которым я его использую (Javascript не является моей сильной стороной).Можете ли вы взглянуть на этот код и помочь мне устранить эту утечку памяти?Я ускорил интервал, который он отображает в этом демонстрационном коде ради времени во время отладки (утечка очевидна даже при проверке процесса в диспетчере задач Windows).Это работает на ASP .Net 3.5 Web Forms, но нет PostBacks, а код полностью HTML, CSS и Javascript.Это худшее в IE (именно это мне нужно использовать для отображения этого).

Редактировать:

  1. Я пробовал использовать разные версииGoogle Maps API (2, 3.0 и 3.6).
  2. Я знаю, что мне не нужно помещать карту из кода примера в Hashtable или Array, но это никак не влияет на утечку памяти.
  3. Я пытаюсь избежать взлома, например, частого обновления страницы или использования статического API Карт Google.
  4. Щедрость достанется тому, кто выяснит, как исправить утечку памяти, или тому, кто четко определит и докажет, почему ее нельзя исправить (если это так).1017 * код:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head id="Head1" runat="server">
        <title>Map Shifter</title>
        <style type="text/css">
            #divMap { height: 400px; width:400px; position:absolute; top:10%; left:10%; border: 2px solid #ff1100; }    
        </style>
        <script type="text/javascript" src="http://maps.google.com/maps/api/js?v=2&sensor=false"></script>
        <script type="text/javascript" language="javascript">
            //Have tried both HashTable and Array (Both Leak)...
            var m_arrMaps = new HashTable(); //new Array();
            var m_Timer;
            function HashTable() {
                return this;
            }
            function LoadMapAndStartShifting() {
                var objMapCenterPoint = new google.maps.LatLng(20.5, -156);
                var objMapOptions = { zoom: 9, center: objMapCenterPoint, mapTypeId: google.maps.MapTypeId.ROADMAP,
                    scaleControl: false, streetViewControl:false, zoomControl: false, mapTypeControl: false, panControl: false
                }
                var map = new google.maps.Map(document.getElementById("divMap"), objMapOptions);
                m_arrMaps["ShiftingMap"] = map;
                setTimeout("ShiftMap(20.5, -156);", 700);
            }
            function ShiftMap(decLat, decLng) {
                var objLatLong = new google.maps.LatLng(decLat, decLng);
                //Have tried setCenter instead of preferred panTo and it still leaks!
                m_arrMaps["ShiftingMap"].panTo(objLatLong);
                if (decLat == 20.5) {
                    //Leaks...
                    ResetTimer(39, -87);
                }
                else {
                    //Still leaks...
                    setTimeout("ShiftMap(20.5, -156);", 700);
                }
            }
            function ResetTimer(decLat, decLng) {
                m_Timer = setTimeout("ShiftMap(" + decLat + ", " + decLng + ");", 700);    
            }    
        </script>
    </head>
    <body onload="LoadMapAndStartShifting();">
        <form id="form1" runat="server">
        <div id="divMap"></div>
       </form>
    </body>
    

Ответы [ 4 ]

2 голосов
/ 19 сентября 2011

Просто еще одна мысль. Вы указываете v = 2, то есть получаете версию 2 этого API. Текущая версия 3.6. Предлагаем попробовать обновить номер версии (или просто удалить параметр v, чтобы получить последнюю стабильную версию) и посмотреть, улучшит ли это ситуацию. Возможно, они убрали любую сборку мусора в более поздних версиях.

2 голосов
/ 16 сентября 2011

Похоже, вы храните только один элемент в объекте "Hashtable" - ["ShiftingMap"] - он не содержит карты, он содержит одну карту.Вы можете просто использовать глобальную переменную для хранения объекта карты.

Единственное повторяющееся распределение - это new google.maps.LatLng(decLat, decLng), который создается для каждого панорамы.

Предложения:

1) Документы для LatLng не дают никаких предупреждений о необходимости явного освобождения объектов, поэтому, вероятно, сборщик мусора должен с этим справиться.

2) Подумайте об общей проблеме - выпытаетесь непрерывно перемещаться по карте Google в течение 6 часов и более.Как вы думаете, почему утечка в вашем коде?Скорее всего, проблема в G Maps.Возможно, загруженные фрагменты изображения карты хранятся локально, поскольку вполне вероятно, что пользователь захочет выполнить панорамирование назад.

В качестве теста попробуйте панорамирование между двумя точками, а не текущее панорамирование по всейземной шар.(Если я правильно понимаю ваше относительное смещение.)

Проверьте, происходит ли утечка со скоростью памяти / час

3) Убедитесь, что разные браузеры по-разному влияют на вашу проблему.Попробуйте Google Chrome.

Добавлено

Я заново обработал ваш демонстрационный код, чтобы вывести вызов LatLng из цикла, и он все еще протекает.Кроме того, лучше всего использовать не строковое значение в вызовах setTimeout, поэтому я тоже это изменил.Я также использовал руководство по Maps API , чтобы установить для типа документа то, что они рекомендуют.

Результат ниже.Утечки на FF и Chrome.Я подал сообщение на официальном форуме API Карт Google v3 .

Кажется очевидным, что метод .panTo протекает.Я полагаю, что ваш следующий шаг - проверить, отвечает ли Гуглер на сообщение.

Демонстрационный пример теста

Переработанный тестовый пример:

<!DOCTYPE html>
<html>
<!-- http://sandbox.kluger.com/map_demo.html -->
<!-- See tutorial http://code.google.com/apis/maps/documentation/javascript/tutorial.html -->
<head>
    <title>Map Shifter</title>
    <style type="text/css">
        #divMap { height: 400px; width:400px; position:absolute; top:10%; 
                  left:10%; border: 2px solid #ff1100; } 
    </style>
    <script type="text/javascript" 
            src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" language="javascript">
        // Globals
        var map,
            mapCenterPoints,
            currentPoint;

        var ShiftMap = function() {
            currentPoint = currentPoint == 0 ? 1 : 0; // update
            map.panTo(mapCenterPoints[currentPoint]);
            setTimeout(ShiftMap, 700);           
        }

        function LoadMapAndStartShifting() {
            mapCenterPoints = [new google.maps.LatLng(20.5, -156),
                               new google.maps.LatLng(39, -87)];
            currentPoint = 0;

            var objMapOptions = { zoom: 9, 
                                  center: mapCenterPoints[currentPoint], 
                                  mapTypeId: google.maps.MapTypeId.ROADMAP,
                                  scaleControl: false, streetViewControl:false, 
                                  zoomControl: false, mapTypeControl: false, 
                                  panControl: false
            }

            map = new google.maps.Map(document.getElementById("divMap"), 
                        objMapOptions);
            setTimeout(ShiftMap, 700);
        }
    </script>
</head>
<body onload="LoadMapAndStartShifting();">
      <div id="divMap"></div>
</body>
</html>
2 голосов
/ 16 сентября 2011

Почему вы создаете хеш-таблицу для карты? Вы можете просто создать свою карту как глобальную переменную. Я был бы удивлен, что это имеет какое-то значение, но ваш комментарий о том, что // // пробовал и HashTable, и Array (Both Leak) ... », заставляет задуматься, зачем вам нужна либо хеш-таблица, либо массив.

Вы также можете избавиться от переменных objMapOptions и objMapCenterPoint, просто передав структуру параметров непосредственно в функцию Map (), а также с помощью latLng в функции panTo ().

<script type="text/javascript" language="javascript">
    var m_Timer, map;

    function LoadMapAndStartShifting() {
        map = new google.maps.Map(document.getElementById("divMap"), { zoom: 9, center: new google.maps.LatLng(20.5, -156), mapTypeId: google.maps.MapTypeId.ROADMAP,
            scaleControl: false, streetViewControl:false, zoomControl: false, mapTypeControl: false, panControl: false
        });
        setTimeout("ShiftMap(20.5, -156);", 700);
    }
    function ShiftMap(decLat, decLng) {
        map.panTo(new google.maps.LatLng(decLat, decLng));
        if (decLat == 20.5) {
            //Leaks...
            ResetTimer(39, -87);
        }
        else {
            //Still leaks...
            setTimeout("ShiftMap(20.5, -156);", 700);
        }
    }
    function ResetTimer(decLat, decLng) {
        m_Timer = setTimeout("ShiftMap(" + decLat + ", " + decLng + ");", 700);    
    }    
</script>

Еще одно предложение, как насчет кэширования карт? Я не знаю, является ли этот пример кода фактически тем, что вы делаете, но если он просто перемещается между двумя картами таким образом, вы не могли бы использовать API статической карты, а также кэшировать изображения и просто использовать javascript для поворота изображения

1 голос
/ 16 сентября 2011

Вы можете попробовать обновить страницу после того, как вы просмотрели данные с помощью JavaScript.Это может освободить память, используемую скриптом, выполняющимся на странице:

Как перенаправить на другую веб-страницу в JavaScript / jQuery?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...