Возможные утечки памяти при использовании Web Workers (Сборщик мусора) - PullRequest
8 голосов
/ 14 сентября 2011

У меня есть приложение, которое вызывает веб-работника после нажатия кнопки.Расчеты переносятся на рабочий, чтобы облегчить пользовательский интерфейс и сделать его отзывчивым на действия пользователя во время выполнения расчетов.

Все идет хорошо, и примерно через 0,8-1,5 с работник отправляет ответ.В worker.onmessage я выполняю все необходимые действия DOM.Но после этого GC появляется и практически блокирует пользовательский интерфейс на 2 или более секунд в зависимости от процессора.Это действительно сбивает с толку, потому что блокировка пользовательского интерфейса - это то, что я хочу предотвратить.

Вот скриншот вкладки временной шкалы / консоли памяти: http://i.imgur.com/zUoHa.jpg

Как вы можете видеть, события GC происходят сразу послевсе манипуляции с DOM.На самом деле есть только одно событие перерисовки (используется 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 зависит от объема данных, которые были отправлены работнику.UPD2: после выключения и загрузки события GC происходят только дважды, блокируя пользовательский интерфейс менее чем на секунду.Hm

1 Ответ

4 голосов
/ 01 октября 2013

Одна вещь, которую следует помнить с Web Workers, и особенно с учетом того, что они используются в вашем примере, это то, что вы клонируете объект, когда отправляете его работнику. Итак, давайте разберемся с этим на глупом примере:

  1. Сделать большой объект (вы сказали 2M в комментарии ... wtf ... wow) - 2M выделено в основном потоке
  2. Публикация на работника, еще 2М в основном потоке, плюс все, что было создано дополнительно в виде пуха в главном потоке, для JSONify вашего объекта / массива, а затем на рабочем месте, где 2М в работнике yay
  3. Chug на этой присоске в работнике ... здесь 2M + в основном потоке просто сидят в ожидании GC, может произойти сейчас, может и не ... GC срабатывает после того, как определенное количество объектов нового поколения достигнет порога. .. как, скажем, после или во время создания тонны новых объектов и элементов dom: D
  4. Рабочий отвечает обратно сообщением, давайте предположим, что 2M, который теперь заново создается в главном потоке для нового 2M (yay), плюс все объекты памяти, необходимые для де-JSONify объекта ... вы видите, куда это идет .

Поскольку вы сказали, что это приложение Chrome (еще один комментарий), то, возможно, вы можете реструктурировать свой код, чтобы использовать Переносимые объекты , чтобы избежать клонирования объектов, создания временных объектов и т. Д. Конечно, чтобы используйте переносимые объекты, которые вам придется реструктурировать как буфер массива, и это все темная магия.

...