Большая утечка памяти JavaScript - PullRequest
1 голос
/ 08 апреля 2011

все!Я работаю над каким-то календарем событий и использую jQuery для внешнего интерфейса и PHP для внутреннего.У меня есть все данные календаря, созданные с помощью PHP и отправленные клиенту в кодировке JSON.

Рассмотрим следующий код (упрощенно):

    jQuery(document).ready(function($) {

    // property which contains calendar object 
    this.Calendar; 
    // get calendar object 
    show_month();

    /* Assign a click event to the next month button */

    $('#cal_month .next span').live('click', function() {
        var month = $(this).attr('id');
        var year  = $(this).attr('class');
        show_month(month, year);
    });

    function show_month(month, year) {
        // delete pointers to the current month object
        window.Calendar = undefined;
        // get new month object
        window.Calendar = get_month(month, year);

        /* doing some stuff with this object here, like output to the 
           document etc., no event bindings */
    }

    function get_month(month, year) {
        var calendar;
        $.ajax({
            type: 'GET',
            dataType: 'json',
            async: false,
            timeout: 100,
            url: '../some_url.php?month='+month+'&year='+year,
            success: function(result) { calendar = result; }
        });
       return calendar;
    }

    var counter = 0;
    while (counter != 1000) {
        $('#cal_month .next span').trigger('click');
        counter ++;
    } 
});

Переключение месяцев вручную, а также создание циклаприводит к огромной утечке памяти.Я прочитал кучу информации об утечках памяти, js-замыканиях и т. Д. Здесь и в целом в Интернете, но я думаю, что у меня все еще есть некоторое недопонимание.Я был бы рад получить некоторые идеи о том, что не так в моем коде.

ОБНОВЛЕНИЕ

Я измеряю использование памяти, наблюдая за firefox.exe (другие браузеры имеют такую ​​же проблему) в диспетчере задач.Запоминание не освобождается, даже когда я перехожу со страницы.И через некоторое время это приводит к значительному падению производительности, поскольку я могу заставить его использовать более 600 Мбайт.

Я также написал цикл для переключения месяцев (добавлен код выше).

ОБНОВЛЕНИЕ 2

Причина, по которой я использовал глобальный режим, заключалась в том, что в моем календаре событий также есть представления недели и дня, поэтому я хочу, чтобы активный объект месяца был доступен дляфункции, которые заботятся об этих двух представлениях, уничтожают их и получают новое, только когда пользователь переключает месяц.Моей проблемой было именно использование глобалов.Это было решено, теперь пытаясь выяснить, как сохранить объект доступным, пока пользователь явно не переключит месяц ...

Кстати, я создал цикл while только для целей бенчмаркинга, он не имеет ничего общего смой фактический код.

Ответы [ 5 ]

4 голосов
/ 08 апреля 2011

Мне любопытно узнать, почему вы думаете, что существует проблема утечки памяти.Я вижу еще две большие проблемы, которые не связаны с памятью, но, возможно, более важны.

Первая проблема - синхронный вызов сервера.В принципе никогда не следует использовать синхронный вызов, поскольку он блокирует браузер во время выполнения запроса. EDIT : выполнение этого 1000 раз в этом цикле заблокирует браузер на 1000 * 100 миллисекунд, что вызовет некоторые, скажем так, проблемы с пользовательским интерфейсом.

Второй - глобальныйКалендарный объект.Помимо того, что вы полагаетесь на непонятное глобальное состояние, вы лишаете возможности делать простые вещи, такие как наличие 2 календарей на одной странице.

Этот код ниже устраняет эти две проблемы.

jQuery(document).ready(function($) {

    $('#cal_month .next span').live('click', function() {
        var month = $(this).attr('id');
        var year  = $(this).attr('class');
        generate_calendar(month, year);
    });

    generate_calendar();

    function calendar_fetch_complete(result) {
        var calendar = result;

        /* doing some stuff with this object here, like output to the 
           document etc.*/
    }

    function generate_calendar(_month, _year) {
        var month = _month || (new Date().getMonth() + 1),
            year  = _year  || (new Date().getYear() + 1900);
        $.ajax({
            type: 'GET',
            dataType: 'json',
            url: '../some_url.php?month='+month+'&year='+year,
            success: calendar_fetch_complete
        });
    }

});
2 голосов
/ 08 апреля 2011

Я предлагаю использовать такие инструменты, как http://www.dynatrace.com/en/, которые действительно иногда помогают.

Проверьте эту статью http://ejohn.org/blog/deep-tracing-of-internet-explorer/ от самого Джона Ресига.

Попробуйте следующий трюк с клопом: Я бы предложил вам попробовать еще одну вещь.Простой трюк с клопом.Если вы не используете операции / mouse на элементе управления UI, просто нажмите на кнопку профилирования firebug.посмотрите, сколько функций и вызовов там происходит, посмотрите, является ли что-то ODD и занимает очень много времени.Это хороший простой трюк, но помогает решить такие проблемы ...:)

http://getfirebug.com/logging

Понимание вывода профилировщика Firebug

1 голос
/ 08 апреля 2011
var counter = 0;
while (counter != 1000) {
    $('#cal_month .next span').trigger('click');
    counter ++;
} 

Что? Согласно этому коду, вы запускаете несколько элементов span 1000 раз и запрашивает синхронный JSON для каждого из этих элементов 1000 раз, что переписывает одну глобальную переменную. Это не утечка памяти, это истощение.

Я предлагаю рефакторинг вашего кода для включения асинхронных запросов и удаления цикла while.

0 голосов
/ 08 апреля 2011

while (counter! = 1000) { $ ('# cal_month .next span'). trigger ('click'); counter ++; }

Похоже, что вы назначаете 1000 триггеров чему-то, не можете ли вы обработать щелчки от родительского объекта?

0 голосов
/ 08 апреля 2011

Вы говорите, что есть утечка памяти, но как вы это определяете?

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

Пожалуйста, найдите правильные инструменты для анализа этого и /или предоставьте больше информации о том, почему вы считаете, что произошла утечка памяти.

...