2016-01-25 42 views
14

2つの大きなキャンバスの内容を比較するアプリケーションのパフォーマンスを向上させようとしています。Webワーカーは大量のメモリを消費します

問題は、比較中にブラウザのメインスレッドがブロックされ、応答しないUIが発生することです。比較関数の実行時間は約10msで、250msまたは500msごとに比較が行われます。

私はweb workerを作成して別のスレッドを使用するというアイデアを思いつきました。今はかなりうまく動作しますが、驚くほどのメモリを消費することに気付きました(FFとChromeで最大600MB、Edgeでは70MB、すべてのブラウザでシングルスレッド版では100MBに達しませんでした)。

私はいくつかの参照を残し、ガベージコレクタはメモリを解放できないと考えました。しかし、しばらくしてから(deletenullまたはundefined変数/データにしようとすると)私は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

EDIT:

私は労働者ごとの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

私は先週報告したので、彼らはそれを修正することを願っています。とにかく私はあなたの修正アプリケーションを実装した後、私は期待通りに動作し、もう一度感謝! –

関連する問題