7

我有一個應用程序在點擊按鈕後調用web worker。這些計算被轉移到工作人員以減輕用戶界面,並在計算時對用戶操作做出響應。使用Web Workers的可能的內存泄漏(垃圾收集器)

一切順利,約0.8-1.5秒後,工作人員發送回覆。在worker.onmessage中,我執行所有需要的DOM操作。但是在這個GC出現之後,根據CPU的不同,它實際上阻塞了用戶界面2秒或更長時間。這讓我很困惑,因爲UI阻止是我想要阻止的。

這裏的時間軸/存儲控制檯選項卡的截圖:http://i.imgur.com/zUoHa.jpg

正如你看到的只是所有DOM操作後GC事件發生。實際上只有一個重繪事件(使用DocumentFragment)。

主要js代碼:

var sortWorker = new Worker('js/contactsorter.js'); 
sortWorker.onmessage = function(e) { 
    var messages = []; 
    e.data.forEach(function(userDoc) { 
     var contactSection = _drawContact(userDoc); 
     messages.push(contactSection); 
    }); 

    meta.append(messages); // this actually appends document fragment as a child 
}; 

sortWorker.postMessage(postMessageData); 

contactsorter.js(工人):

onmessage = function(e) { 
    var uid, output = [], usersStat = {}; 

    // calculations... 

    postMessage(output); 
    close(); 
}; 

有什麼辦法,以避免在這個地方或沒有這些GC事件?

UPD:在我看來,GC事件(s)時間取決於發送給worker的數據量。 UPD2:關機和啓動後,GC事件只發生兩次,因此阻塞UI的時間不到一秒鐘。嗯?

+0

對象有多大?多少?我們在聊什麼樣的數字?你創建了哪些DOM節點? GC事件是否與排序的聯繫數量成線性比例? –

+0

JSON.stringify說它大概是2M。這些是有對象作爲子女的對象。工作人員響應(它輸出數組)後,我創建DocumentFragment並追加約。 400「div」元素。之後我將片段追加到DOM。關於最後一個問題 - 我需要重寫我的代碼來進行測試,所以稍後我會對此進行評論。順便說一句:新UPD –

+0

關於最後一個問題:不,GC事件不根據數據量進行縮放。此外,我甚至無法在時間線http://i.imgur.com/psGpr.png上找到它,儘管在這段時間內UI正在計時。 –

回答

3

Web Workers需要記住的一件事情,尤其是當您將它們用於您的示例中時,您將克隆對象發送給工作人員。 (你說的2M的評論... WTF ......哇)

  1. 做大對象 - 2M的主線程
  2. 郵政工人,2M的分配:所以讓我們通過這一個愚蠢的例子運行主線程仍然加上任何額外的東西在主線程中創建爲絨毛JSON化你的對象/數組,然後關閉到工人2M在工作人員yay
  3. Chug在工人的吸盤...在這裏2M +在主線程只是坐在等待GC,現在可能發生,可能不會......在一定數量的新一代物體達到閾值之後,GC觸發器......就像在創建大量新對象和dom元素之後或期間所說的那樣: D
  4. 工作人員回覆一條消息,讓我們假設2M現在在新的2M(yay)的主線程中重新創建,再加上任何需要對對象進行JSON化的絨毛內存對象......您會看到它將發生什麼。

既然你說,這是一個Chrome應用程式(另一評論),那麼也許你可以調整你的代碼,以利用Transferable Objects避免克隆臨時對象等的創建對象當然,要使用轉讓的對象,你必須重組爲陣列緩衝區,這本身就是一個黑魔法。

+0

*「您在評論中說過2M ... wtf ...哇 - 」 - 對於諸如圖形,音頻或分析軟件等應用而言,通常要大得多。我在這裏傳遞12 GB(!)的數組沒有問題,使用可轉移的。 –

+0

@JohnWeisz - 同意,最近我還經常使用WebAudio等較大的對象。但在回到2013年底的機器,似乎很多。我認爲他的實際問題主要與創建大量臨時對象以及作爲其循環或映射器的一部分有關,更不用說他在DOM中做什麼的未知數。 –

相關問題