如何使用Webworker的postMessage传输大型对象? [英] How to transfer large objects using postMessage of webworker?

查看:626
本文介绍了如何使用Webworker的postMessage传输大型对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经读到,使用Web Worker的后消息,可传输对象可以非常快速地传输.根据可传递对象,它们可以是数组缓冲区或消息端口.>

问题是,如何将大尺寸(30 mb)的任意对象转换为可传输对象,并将其作为参数传递给postmessage.据我了解,我可以将数组转换为json字符串,然后将json字符串转换为原始字节数据并将其存储在数组对象内部.但是,这似乎违背了快速转移的目的.

有人可以启发我将一个对象作为可传递的对象传递吗?或者甚至可以传递它吗?

提前谢谢!

解决方案

这种误解在这里经常发生.您在想,可以编写一些快速javascript代码将大型对象转换为可转让对象.但是确实,正如您所说的那样,您编写的任何转换代码都无法达到目的.而且,数据越复杂,丢失的速度就越快.

对象通常(在传输时)由本机 结构化克隆算法 (使用实现定义的格式,并且确定为最佳).您编写的任何JavaScript代码最有可能都比结构化克隆慢,同时实现相同的目标-以二进制格式传输数据.

可传输对象的目的是允许传输二进制数据,例如图像(来自画布),音频或视频.无需经过结构化克隆算法即可处理这些数据,这就是为什么要添加可传输接口的原因.而且即使是这些,效果也微不足道-请参阅关于可传输速度的答案.

最后一点,我编写了一个基于原型的库,该库将javascript对象转换为ArrayBuffer并返回.速度较慢,尤其是对于像JSON这样的数据.它的优点(以及您编写的任何类似代码的优点)是:

  1. 您可以定义自定义对象转换
  2. 您可以使用继承(例如,发送自己的类型,例如 Foo )

用于传输类似于对象的JSON的代码

如果您的数据类似于JSON,请坚持使用结构化克隆,不要进行传输.如果您不信任我,请使用此代码进行测试.您会发现它比普通的 postMessage 慢.

  var object = {dd:"ddd",sub:{xx:"dd"},num:666};var string = JSON.stringify(object);var uint8_array = new TextEncoder(document.characterSet.toLowerCase()).encode(string);var array_buffer = uint8_array.buffer;//现在传输数组缓冲区worker.postMessage(array_buffer,[array_buffer]) 

相反的转换,考虑到您有一些 ArrayBuffer :

 //让我为仿真生成一些数组缓冲区var array_buffer = new Uint8Array([123,34,100,100,34,58,34,100,100,100,34,44,34,115,117,98,34,58,123,34,120,120,34,58,34,100,100,34,125,44,34,110,117,109,34,58,54,54,54,54,125]).buffer;//现在开始解码var解码器=新的TextDecoder("utf-8");var view = new DataView(array_buffer,0,array_buffer.byteLength);var string = encoder.decode(view);var object = JSON.parse(string); 

I have read that transferable objects can be transferred really fast using postmessage of web worker. According to this transferable objects are either arraybuffer or messageport.

Question is, how do I convert say an arbitrary object that is of large size (30 mb) to a transferable object and pass it as an argument to postmessage. From what I understand I can convert my array to json string and then convert json string to raw byte data and store that inside of an array object. However, this seems to defeat the purpose of fast transferring.

could someone enlighten me to pass an object as transferable object or if it's even possible?

Thanks in advance!

解决方案

This misconception is quite recurring here. You're imagining that it's possible to write some fast javascript code to convert your large object into transferable. But indeed, any conversion code you write defeats the purpose, just as you said. And the more complex data, the more speed you lose.

Objects are normally (when not transfering) converted by native structured clone algorithm (which uses implementation defined format and sure is optimal). Any javascript code you write will most likely be slower than structured clone, while achieving the same goal - transferring data as binary.

The purpose of transferable objects is to allow transfer for binary data, such as images (from canvas), audio or video. These kinds of data can be transferred without being processed by structured clone algorithm, which is why transferable interface was added. And the effect is insignificant even for these - see an answer about transferable speed.

As a last note, I wrote a prototype based library that converts javascript objects to ArrayBuffer and back. It's slower, especially for JSON like data. It's advantages (and advantages of any similar code you write) are:

  1. You can define custom object conversions
  2. You can use inheritance (eg. sending your own types, like Foo)

Code to transfer JSON like object

If your data is like JSON, just stick to structured clone and do not transfer. If you don't trust me, test it with this code. You will see it's slower than normal postMessage.

var object = {dd:"ddd", sub:{xx:"dd"}, num:666};
var string = JSON.stringify(object);
var uint8_array = new TextEncoder(document.characterSet.toLowerCase()).encode(string);
var array_buffer = uint8_array.buffer;
// now transfer array buffer
worker.postMessage(array_buffer, [array_buffer])

The opposite conversion, considering you have some ArrayBuffer:

// Let me just generate some array buffer for the simulation
var array_buffer = new Uint8Array([123,34,100,100,34,58,34,100,100,100,34,44,34,115,117,98,34,58,123,34,120,120,34,58,34,100,100,34,125,44,34,110,117,109,34,58,54,54,54,125]).buffer;
// Now to the decoding
var decoder = new TextDecoder("utf-8");
var view = new DataView(array_buffer, 0, array_buffer.byteLength);
var string = decoder.decode(view);
var object = JSON.parse(string);

这篇关于如何使用Webworker的postMessage传输大型对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆