2016-01-25 80 views
14

我試圖改進性能,在我的應用程序比較兩個大畫布的內容。Web Worker消耗大量內存

問題是,在比較瀏覽器的主線程比較期間,阻塞了什麼導致無響應的UI。比較功能的執行時間約爲10ms,每250ms或500ms進行一次比較。

要解決這個問題,我想出了使用另一個線程的想法,創建一個web worker。現在它運行得相當不錯,但我意識到它會消耗大量的內存(在FF和Chrome中高達600MB--在Edge中高達70MB,在所有瀏覽器上從未達到單線程版本的100MB)。

我以爲我留下了一些引用和垃圾收集器無法釋放內存。然而,經過一段時間(整個一天剝離我的應用程序的片斷,並試圖delete,nullundefined變量/數據)我創建了下面的提琴1MB ArrayBuffer(即使我通過傳遞),但沒有任何處理和你可以看到它消耗大量的內存。

任何想法如何解決這個問題(任何替代解決方案或任何可能的工人改進)以及問題出在哪裏?

var sortFilterDataWorker = function() { 
    onmessage = function image2compare(ev) { 
     postMessage('hi'); 
    }; 
}.toString(); 

/* PREPARE WORKER AS STRING TO CREATE JS BLOB FILE */ 
sortFilterDataWorker = sortFilterDataWorker.slice(sortFilterDataWorker.indexOf('{') + 1, -1).trim(); 

var blob = new Blob([sortFilterDataWorker]) // create blob file with worker code 
    , blobUrl = window.URL.createObjectURL(blob) // create pseudo url to blob file 
    , compareWorker = new Worker(blobUrl) 
    ; 

setInterval(function(){ 
    var oneMB = new ArrayBuffer(8388608); 
    compareWorker.postMessage(oneMB, [oneMB]); // transpile ArrayBuffer 
}, 250); 

FIDDLE

編輯:

我發現,如果我終止工人每n重複和更快地創建新的釋放內存。但它仍然不是一個只有古玩的解決方案。

回答

8

我發現如果我從開發人員工具 - >時間軸手動運行垃圾回收器,它會清除所有的內存。同樣,如果我從控制檯開始與Worker上下文進行交互,調用函數似乎會隨機觸發成功的gc。

基於此,我會說沒有懸掛引用,但通過傳輸接收對象可能不會強制進行gc檢查,因爲會有新的分配請求。

與響應傳送目標回似乎要解決的問題:

postMessage('hi', [ev.data]); // process usage stays around 50MB 

作爲替代方案,確保工人是不平凡的,需要做正常的分配也似乎正確觸發GC,即:

postMessage('hi'); 
    var twoMB = new ArrayBuffer(8388608); // usage cycles 70MB - ~220MB 
+0

我會給你買一隻熊,如果可以的話,非常感謝! –

+1

謝謝@Etsitra,您最小化的測試案例非常完美。您還應該直接將錯誤提交給chromium.org和bugzilla,以使環境最終符合您的需求而無需解決方法。 – lossleader

+3

我上週做過報道,所以希望他們能解決這個問題。無論如何,在我實施你的修復程序後,終於表現得如我所料,再次感謝! –