Web Workers — переносимые объекты для JSON

Веб-воркеры HTML 5 работают очень медленно при использовании worker.postMessage для большого объекта JSON. Я пытаюсь понять, как передать объект JSON веб-воркеру, используя типы «Переносимые объекты» в Chrome, чтобы увеличить скорость этого.

Вот что я имею в виду, и кажется, что это должно немного ускорить: http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fast

У меня возникли проблемы с поиском хорошего примера этого (и я не верю, что хочу использовать ArrayBuffer). Любая помощь будет оценена по достоинству.

Я представляю что-то вроде этого:

worker = new Worker('workers.js');

var large_json = {};
for(var i = 0; i < 20000; ++i){
   large_json[i] = i;
   large_json["test" + i] = "string";
};

//How to make this call to use Transfer Objects? Takes approx 2 seconds to serialize this for me currently.
worker.webkitPostMessage(large_json);

person kclem06    schedule 06.07.2012    source источник
comment
Именно здесь работники в их нынешнем обличии падают, поскольку они не имеют связи с родительским скриптом, поэтому все, что вы хотите передать им, требует утомительной операции копирования. Подход Webkit по ссылке, безусловно, правильный путь. Кроме этого, меня поражают два момента: если вы завалены 2-секундной задержкой, это, вероятно, сводит на нет любую экономию, которую вы могли бы получить в противном случае, используя веб-воркеров, так что вы могли бы также избегать их и, таким образом, также избегать сериализация. 2) Как насчет веб-SQL для данных такого размера - быстрее?   -  person Mitya    schedule 06.07.2012
comment
В основном мне нужно манипулировать JSON и передавать его обратно, поэтому я не верю, что веб-SQL сработает. В моих обычных случаях я бы не передал такой большой объект JSON, но я использовал его для целей тестирования/демонстрации. Из того, что я читал, я полагаю, что передаваемые объекты сделают его очень быстрой операцией передачи по ссылке, что приведет к чрезвычайно своевременной передаче, намного меньше текущих 2 секунд. Однако я не могу найти ни одного примера того, как это сделать на самом деле.   -  person kclem06    schedule 06.07.2012
comment
сложные типы, такие как объекты File, Blob, ArrayBuffer и JSON. -- Похоже, это должно поддерживаться: developer.mozilla.org/en/Using_web_workers   -  person kclem06    schedule 07.07.2012
comment
Я столкнулся с той же самой проблемой. Решение, с которым я играл, заключалось в использовании ArrayBuffer и преобразовании json в строку, а затем преобразовании этой строки в UInt16Array (updates.html5rocks.com/2012/06/), но этот процесс также требует много времени. До сих пор не найден какой-либо метод отправки больших объектов JSON в рабочий процесс и из него таким образом, чтобы использование веб-воркеров того стоило: -/   -  person stinkycheeseman    schedule 13.07.2012
comment
@stinkycheeseman - Спасибо за вклад, я хотел попробовать это, но я не был точно уверен, как сделать преобразование. Что касается времени для простой передачи ArrayBuffer (без преобразования его в ArrayBuffer), насколько это примерно быстро? Я бы предположил, что это максимум несколько мс, но я на самом деле не пробовал.   -  person kclem06    schedule 13.07.2012
comment
@ kclem06 да, это должно быть почти мгновенно, но я тоже не зашел так далеко.   -  person stinkycheeseman    schedule 14.07.2012
comment
взгляните на developer.mozilla.org/en-US/docs/ Web/API/Channel_Messaging_API   -  person mb21    schedule 22.08.2017


Ответы (3)


Использование переносимого объекта не поможет, если вам нужно создать его с нуля из существующего массива Json (это очень близко к клонированию...)

Откуда берутся данные Json? Один из возможных способов перенести всю тяжелую работу на рабочий поток — заставить его извлекать данные с помощью XmlHttpRequest, преобразовывать их и отправлять в поток пользовательского интерфейса. Таким образом, высокая стоимость клонирования возникает в рабочем потоке, и хотя это займет столько же времени, сколько и в потоке пользовательского интерфейса, оно не заблокирует ваше приложение.

person AlexG    schedule 07.07.2013

Хорошо, я сделал это, я не знаю, хорошо это или плохо, идеальный или худший способ сделать это. Я только что это сделал. в рабочем файле

var data = e.data;
var string = String.fromCharCode.apply(null, new Uint16Array(data));
var objnow = JSON.parse(string);

в html-файле

function str2ab(str) {
   var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
   var bufView = new Uint16Array(buf);
   for (var i=0, strLen=str.length; i<strLen; i++) {
     bufView[i] = str.charCodeAt(i);
   }
   return buf;
 }
function stop() {
 var obj = {'cmd': 'stop', 'msg': 'Bye'};
 var str= JSON.stringify(obj);
 var arbfr = str2ab(obj);
 worker.postMessage(arbfr,[arbfr]);
}

И теперь это работает, я могу отправить объект json, передать.

person Muhammad Umer    schedule 17.06.2013

Не используя «Переносимые объекты», но это может решить вашу проблему.

Вы также можете попытаться оптимизировать представление данных. Например. ваш пример у меня занимает ~1350 мс для упаковки/распаковки (Google Chrome 19), но следующий код выполняется примерно в 25 раз быстрее (50 мс):

console.time('json');
var a = [], test = [];
for(var i = 0; i < 20000; ++i){
   a.push(i);
   test.push("string");
};
var large_json = {
  a: a.join(','),
  test: test.join(',')
};
large_json = JSON.parse(JSON.stringify(large_json));
large_json.a = large_json.a.split(",");
large_json.test = large_json.test.split(",");
console.timeEnd('json');
person kirilloid    schedule 01.08.2012