簡體   English   中英

重大JavaScript內存泄漏

[英]Major JavaScript memory leak

大家! 我正在處理某種事件日歷,並且將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+ Mb,它會導致性能下降。

我還寫了一個循環來切換月份(上面添加了代碼)。

更新2

我使用global的原因是,在我的事件日歷中,我還具有周和日視圖,因此我希望活動的月份對象可用於處理這兩個視圖的功能,並且僅當用戶使用時銷毀它並獲得新的視圖切換月份。 我的問題恰恰是全局變量的用法。 解決了那個問題,現在試圖弄清楚如何使對象保持可用狀態,直到用戶明確切換月份為止。

順便說一句,我創建了一個while循環,僅用於基准測試,它與我的實際代碼無關。

我很好奇您為什么會認為存在內存泄漏問題。 我看到另外兩個與內存無關的大問題,但也許更重要。

第一個問題是同步服務器調用。 你應該在主從來沒有使用同步調用,因為它鎖定瀏覽器,同時請求正在進行中。 編輯 :在該循環中執行1000次將最多鎖定瀏覽器1000 * 100毫秒,這會引起一些用戶體驗問題。

第二個是全局Calendar對象。 除了依靠混亂的全局狀態之外,您還無法做一些簡單的事情,例如在同一頁面上有兩個日歷。

下面的代碼修復了這兩個問題。

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
        });
    }

});

我建議使用諸如http://www.dynatrace.com/en/之類的工具,這些工具有時會很有幫助。

請查看John Resig自己的這篇文章http://ejohn.org/blog/deep-tracing-of-internet-explorer/

嘗試以下螢火蟲把戲:建議您再嘗試一件事。 簡單的螢火蟲把戲。 當您不在UI控件上使用/鼠標操作時,只需單擊Firebug的配置文件按鈕。 看看有多少個函數正在發生調用,看看是否有些東西是奇數的並且花費了很長時間。 它是一個很好的簡單技巧,但可以幫助解決此類問題... :)

http://getfirebug.com/logging

了解Firebug分析器輸出

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

什么? 根據此代碼,您將觸發多個span元素1000次,並為這些元素中的每一個請求同步JSON 1000次,這將重寫單個全局變量。 這不是內存“泄漏”,而是精疲力盡。

我建議將您的代碼重構為包括異步請求,並取出while循環。

您說存在內存泄漏,但是如何確定呢?

可能是您只是在查看瀏覽器進程的內存使用情況。 瀏覽器對內存所做的任何操作都不一定與您在javascript中所做的事情有關。 可能是javascript引擎沒有釋放它認為會再次使用的內存空間-無論您當前是否正在使用它。

請找到正確的工具進行分析和/或提供更多有關為什么您認為內存泄漏的信息。

while(count!= 1000){$('#cal_month .next span')。trigger('click'); 計數器++; }

看起來您正在將1000個觸發器分配給某個對象-您不能處理來自父對象的任何點擊嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM