Уеб работници - прехвърляеми обекти за 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 обекти към и от worker по такъв начин, че да си струва използването на уеб worker :-/   -  person stinkycheeseman    schedule 13.07.2012
comment
@stinkycheeseman - Благодаря за приноса, исках да опитам това, но не бях сигурен как точно да направя преобразуването. По отношение на времето за просто прехвърляне на ArrayBuffer (без преобразуването му в ArrayBuffer), приблизително колко бързо е това? Предполагам, че е най-много няколко ms, но всъщност не съм го пробвал.   -  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

Въпреки че не използвате „Прехвърляеми обекти“, но това може да реши проблема ви.

Можете също да опитате да оптимизирате представянето на вашите данни. напр. вашият пример отнема ~1350ms за опаковане/разопаковане за мен (Google Chrome 19), но следният код се изпълнява ~25 пъти по-бързо (50ms):

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