Web Workers - JSON 的可传输对象

Posted

技术标签:

【中文标题】Web Workers - JSON 的可传输对象【英文标题】:Web Workers - Transferable Objects for JSON 【发布时间】:2012-07-07 03:07:47 【问题描述】:

在大型 JSON 对象上使用 worker.postMessage 时,html 5 Web 工作者非常慢。 我试图弄清楚如何将 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);

【问题讨论】:

这是工作人员(以他们当前的形式)失败的地方,因为他们与父脚本没有任何联系,因此您想要传递给他们的任何内容都涉及令人厌烦的复制操作。 Webkit 的“通过引用传递”方法绝对是要走的路。除此之外,有两点让我印象深刻:如果你被 2 秒的延迟所困扰,那可能会破坏你通过使用网络工作者可能获得的任何节省,所以你最好避免它们,因此,也避免序列化。 2) 对于这种大小的数据,Web SQL 怎么样 - 更快吗? 我基本上需要操作 JSON 并将其传输回来,所以我不相信 web SQL 会起作用。在我的正常情况下,我不会传输这么大的 JSON 对象,但我将它用于测试/演示目的。我相信从我一直在阅读的内容中可以看出,Transferable Objects 将使它成为一个非常快速的按引用传递操作,从而实现非常及时的传输,远低于当前的 2 秒。但是,我找不到任何实际操作的示例。 "文件、Blob、ArrayBuffer 和 JSON 对象等复杂类型。" -- 似乎应该支持:developer.mozilla.org/en/Using_web_workers 我面临着同样的问题。我正在玩弄的解决方案是使用 ArrayBuffer 并将 json 字符串化,然后将该字符串转换为 UInt16Array (updates.html5rocks.com/2012/06/…),但该过程也非常耗时。仍然没有找到任何将大型 JSON 对象发送到工作人员和从工作人员发送出的任何方法,以使使用网络工作人员值得:-/ @stinkycheeseman - 感谢您的输入,我想试试这个,但我不确定如何进行转换。关于仅传输 ArrayBuffer(不将其转换为 ArrayBuffer)的时间,大约有多快?我想它最多只有几毫秒,但我还没有真正尝试过。 【参考方案1】:

如果您必须从现有的 Json 数组从头开始构建它,那么使用可转移对象将无济于事(这非常接近克隆......)

Json 数据从何而来?保持工作线程上所有繁重工作的一种可能方法是让它使用 XmlHttpRequest 获取数据,对其进行转换并将其发送到 UI 线程。这样,高昂的克隆成本发生在工作线程上,虽然它需要与 UI 线程中相同的时间,但不会阻塞您的应用。

【讨论】:

【参考方案2】:

好的,我这样做了,我不知道这样做是好是坏,是理想的还是最差的。我刚刚做完。 在工作文件中

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 对象,传输。

【讨论】:

【参考方案3】:

虽然不使用“可转移对象”,但这可能会解决您的问题。

您也可以尝试优化您的数据表示。 例如。您的示例需要 ~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');

【讨论】:

以上是关于Web Workers - JSON 的可传输对象的主要内容,如果未能解决你的问题,请参考以下文章

Akka(34): Http:Unmarshalling,from Json

序列化和json

JSON转换和序列化的区别

json中load和loads区别

json中load和loads区别

python -mSimpleHTTPServer 开启一个简单的http服务器,可传输文件