我正在研究 web worker,我正在将大量数据传递给 web worker,这需要很多时间。我想知道发送数据的有效方法。
我尝试了以下代码:
var worker = new Worker('js2.js');
worker.postMessage( buffer,[ buffer]);
worker.postMessage(obj,[obj.mat2]);
if (buffer.byteLength) {
alert('Transferables are not supported in your browser!');
}
原文由 vicky 发布,翻译遵循 CC BY-SA 4.0 许可协议
更新
现代版本的 Chrome、Edge 和 Firefox 现在支持 SharedArrayBuffers(虽然在撰写本文时不支持 safari, 请参阅 MDN 上的 SharedArrayBuffers ),因此与可转移( 您可以查看 MDN 了解 SharedArrayBuffers 的所有权衡和要求)。
更新:
根据 Mozilla 的说法,SharedArrayBuffer 已在所有主流浏览器中被禁用,因此以下编辑中描述的选项不再适用。
编辑: 现在有另一个选项,它正在发送一个 sharedArray 缓冲区。这是 ES2017 在共享内存和原子性下的一部分,现在在 FireFox 54 Nightly 中得到支持。如果您想了解它,可以查看 此处。我可能会写一些东西并将其添加到我的答案中。我也会尝试添加到性能基准中。
回答原来的问题:
@MichaelDibbets answer 的替代方法,他将对象的副本发送给网络工作者,使用的是零拷贝的可 转移对象。
它表明您打算让您的数据可传输,但我猜它没有成功。因此,我将为您和未来的读者解释某些数据可传输的含义。
“通过引用”传输对象(尽管这不是下一段引述中解释的完美术语)不仅仅适用于任何 JavaScript 对象。它必须是可传输的数据类型。
- Google 的 Eric Bidelman 开发人员,来源: html5rocks
唯一的问题是目前只有 两件事可以转让。 ArrayBuffer 和 MessagePort 。 (希望 Canvas Proxies 稍后推出)。 ArrayBuffers 不能直接通过它们的 API 进行操作,应该用于创建 类型化数组对象 或 DataView 以提供缓冲区的特定视图并能够对其进行读取和写入。
来自 html5rocks 链接
所以根据你的
应该以极快的速度执行,并且应该以零拷贝的方式传输。唯一的问题是,如果您的
buffer
或obj.mat2
不是 ArrayBuffer 或可转移的。您可能会将 ArrayBuffers 与 类型化数组 的视图混淆,而不是您应该使用其缓冲区的内容。所以如果你有这个 ArrayBuffer 并且它是 Int32 表示。 (虽然变量标题为视图,但它不是 DataView,但 DataView 确实具有属性缓冲区,就像类型化数组一样。同样在编写本文时,MDN 使用名称“view”来表示调用类型化数组构造函数的结果所以我认为这是定义它的好方法。)
这是你 不 应该做的(发送视图)
这是你 应该 做的(发送 ArrayBuffer)
这些是 在 plnkr 上运行此测试 后的结果。
编辑:正如 @Bergi 在 评论 中所述,如果你有视图,你根本不需要缓冲区变量,因为你可以像这样发送
view.buffer
正如给未来读者的旁注,只是发送一个 ArrayBuffer 而没有最后一个参数指定 ArrayBuffers 是什么,你不会以可转移的方式发送 ArrayBuffer
换句话说,在发送可转让资产时,您需要这样:
不是这个:
编辑:最后一个注意事项,因为您正在发送缓冲区,请不要忘记在 webworker 收到缓冲区后将其变回视图。一旦它成为一个视图,您就可以再次操作它(从中读取和写入)。
为了赏金:
至于网络浏览器限制发送一定大小的东西,我不太确定,但是从 Eric Bidelman 在谈论工人时他确实提出了一个 50 MB 的文件正在传输而不使用可传输数据类型的情况下,引用了 html5rocks 上的条目在数百毫秒内,如我的测试所示,使用可传输数据类型仅需大约一毫秒。老实说,这 50 mb 是相当大的。
纯粹是我个人的意见,但我认为除了数据类型本身的限制外,您发送的可传输或不可传输数据类型的文件大小没有限制。当然,您最大的担心可能是浏览器停止长时间运行的脚本,如果它必须复制整个内容并且不是零复制和可传输的。
希望这篇文章有所帮助。老实说,在此之前我对可转让资产一无所知,但通过一些测试和 Eric Bidelman 的博客文章弄清楚它们很有趣。