2016-01-25 7 views
14

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

Проблема в том, что во время сравнения основной поток браузера блокируется, что приводит к невосприимчивому пользовательскому интерфейсу. Время выполнения функции сравнения занимает около 10 мс, а сравнение происходит каждые 250 мс или 500 мс.

Чтобы решить эту проблему, я придумал использовать другой поток, создав web worker. Он работает довольно хорошо прямо сейчас, но я понял, что он потребляет безумный объем памяти (до 600 МБ в FF и Chrome - в Edge до 70 МБ, он никогда не достигал 100 МБ в однопоточной версии во всех браузерах).

Я думал, что оставил некоторые ссылки, и сборщик мусора не может освободить память. Однако через некоторое время (целый день снятия моего приложения с кусков и попыток delete, null или undefined переменных/данных) Я создал скрипку ниже, в которой я отправляю 1 МБ 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:

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

ответ

8

Я обнаружил, что если я запускаю сборщик мусора вручную из инструментов разработчика -> Timeline, он очищает всю память. Аналогичным образом, если я начну взаимодействовать с контекстом Worker с консоли, вызывающие функции, похоже, случайным образом запускают успешный gc.

Основываясь на этом, я бы сказал, что нет вешающей ссылки, но что получение объектов посредством передачи может не привести к проверке gc в качестве новых запросов на распределение.

Передача объекта обратно с ответом, кажется, чтобы обойти эту проблему:

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

В качестве альтернативы, убедившись, что работник не является тривиальной и нужно будет делать нормальные распределения также, кажется, правильно вызвать дс, то есть:

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

Я бы купил вам медведя, если мог, спасибо большое! –

+1

Благодаря @Etsitra ваш свернутый тестовый пример был действительно совершенным. Вы также должны записывать ошибки непосредственно на chromium.org и bugzilla, чтобы среда в конечном итоге соответствовала вашим потребностям без обходных решений. – lossleader

+3

Я сообщил об этом на прошлой неделе, поэтому надеюсь, что они это исправит. Во всяком случае, после того, как я внедрил ваше приложение для исправления, вы, наконец, ведете себя так, как я ожидал, еще раз спасибо! –

Смежные вопросы