gpt4 book ai didi

javascript - 如何将大数据传递给网络 worker

转载 作者:行者123 更新时间:2023-12-02 17:10:55 25 4
gpt4 key购买 nike

我正在研究网络 worker ,我正在将大量数据传递给网络 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!');
}

最佳答案

更新
Chrome、Edge 和 Firefox 的现代版本现在支持 SharedArrayBuffers(尽管在撰写本文时还不是 safari see SharedArrayBuffers on MDN),因此与可传输数据相比,这将是快速传输数据的另一种可能性( you can see MDN for all the trade offs and requirements of SharedArrayBuffers )。
更新 :
According to Mozilla SharedArrayBuffer 已在所有主要浏览器中禁用,因此以下编辑中描述的选项不再适用。

Note that SharedArrayBuffer was disabled by default in all majorbrowsers on 5 January, 2018 in response to Spectre.


编辑:现在有另一种选择,它正在发送一个 sharedArray 缓冲区。这是共享内存和原子下 ES2017 的一部分,现在 FireFox 54 Nightly 支持。如果你想阅读它,你可以看 here .我可能会写一些东西并将其添加到我的答案中。我也会尝试添加到性能基准测试中。
要回答原始问题:

I am working on web workers and I am passing large amount of data toweb worker, which takes a lot of time. I want to know the efficientway to send the data.


@MichaelDibbets answer 的替代方案,他将对象的副本发送给网络 worker ,正在使用 transferrable object这是零拷贝。
它表明您打算使您的数据可传输,但我猜它没有成功。因此,我将向您和 future 的读者解释某些数据可传输的含义。
“通过引用”传输对象(尽管这不是它的完美术语,正如下一个引用中所解释的那样)不仅仅适用于任何 JavaScript 对象。它必须是可传输的数据类型。

[With Web Workers] Most browsers implement the structured cloningalgorithm, which allows you to pass more complex types in/out ofWorkers such as File, Blob, ArrayBuffer, and JSON objects. However,when passing these types of data using postMessage(), a copy is stillmade. Therefore, if you're passing a large 50MB file (for example),there's a noticeable overhead in getting that file between the workerand the main thread.

Structured cloning is great, but a copy can take hundreds ofmilliseconds. To combat the perf hit, you can use TransferableObjects.

With Transferable Objects, data is transferred from one context toanother. It is zero-copy, which vastly improves the performance ofsending data to a Worker. Think of it as pass-by-reference if you'refrom the C/C++ world. However, unlike pass-by-reference, the 'version'from the calling context is no longer available once transferred tothe new context. For example, when transferring an ArrayBuffer fromyour main app to Worker, the original ArrayBuffer is cleared and nolonger usable. Its contents are (quiet literally) transferred to theWorker context.


- 埃里克·比德曼 Google 的开发人员,来源: html5rocks
唯一的问题是只有 two things that are transferrable截至目前。 ArrayBuffer , 和 MessagePort . ( Canvas Proxies 希望以后会来)。 ArrayBuffers 不能通过它们的 API 直接操作,应该用于创建 typed array objectDataView给出缓冲区的特定 View 并能够对其进行读写。
来自 html5rocks 链接

To use transferrable objects, use a slightly different signature ofpostMessage():

worker.postMessage(arrayBuffer, [arrayBuffer]);


window.postMessage(arrayBuffer, targetOrigin, [arrayBuffer]);

The worker case, the first argument is the data and the second is thelist of items that should be transferred. The first argument doesn'thave to be an ArrayBuffer by the way. For example, it can be a JSONobject:

worker.postMessage({data: int8View, moreData: anotherBuffer}, [int8View.buffer, anotherBuffer]);


所以根据你的
var worker = new Worker('js2.js');
worker.postMessage(buffer, [ buffer]);
worker.postMessage(obj, [obj.mat2]);
应该以极快的速度执行并且应该被转移零拷贝。唯一的问题是如果您的 bufferobj.mat2不是 ArrayBuffer或可转让。您可能会将 ArrayBuffers 与 typed array 的 View 混淆而不是你应该使用它的缓冲区。
所以如果你有这个 ArrayBuffer 并且它是 Int32 表示。 (虽然变量的标题是 View ,但它不是数据 View ,但数据 View 确实有一个属性缓冲区,就像类型化数组一样。另外,在编写此文件时,MDN 使用名称“ View ”作为调用类型化数组构造函数的结果所以我认为这是定义它的好方法。)
var buffer = new ArrayBuffer(90000000);
var view = new Int32Array(buffer);
for(var c=0;c<view.length;c++) {
view[c]=42;
}
这是你应该做的 不是 做(发送 View )
worker.postMessage(view);
这就是你 应该做(发送 ArrayBuffer)
worker.postMessage(buffer, [buffer]);
这些是运行后的结果 this test on plnkr .
Average for sending views is 144.12690000608563
Average for sending ArrayBuffers is 0.3522000042721629
编辑:如 @Bergi 所述在 the comments如果您有 View ,则根本不需要缓冲区变量,因为您只需发送 view.buffer像这样
worker.postMessage(view.buffer, [view.buffer]);
正如对 future 读者的旁注一样,只发送一个 ArrayBuffer 而没有指定 ArrayBuffers 是什么的最后一个参数,您将不会发送 ArrayBuffer 可转移
换句话说,在发送可转让文件时,您需要:
worker.postMessage(buffer, [buffer]);
不是这个:
worker.postMessage(buffer);
编辑:最后一个注意事项,因为您正在发送缓冲区,一旦 webworker 收到它,请不要忘记将缓冲区转换回 View 。一旦它成为一个 View ,您就可以再次操作它(从中读取和写入)。
对于赏金:

I am also interested in official size limits for firefox/chrome (notonly time limit). However answer the original question qualifies forthe bounty (;


至于网络浏览器发送特定大小的内容的限制,我不完全确定,但从埃里克·比德曼 (Eric Bidelman) 在 html5rocks 上的那篇引述中谈到 worker 时,他确实提出了一个 50 mb 的文件,在不使用可传输数据类型的情况下传输在数百毫秒内,并且如我的测试所示,使用可传输数据类型仅需大约一毫秒。老实说,其中 50 mb 相当大。
纯粹是我自己的意见,但我不认为除了数据类型本身的限制之外,您在可传输或不可传输数据类型上发送的文件大小没有限制。当然,如果浏览器必须复制整个内容并且不是零复制和可传输的,那么您最大的担忧可能是浏览器停止长时间运行的脚本。
希望这篇文章有帮助。老实说,在此之前我对可转移性一无所知,但是通过一些测试和 Eric Bidelman 的博客文章弄清楚它们很有趣。

关于javascript - 如何将大数据传递给网络 worker ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19152772/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com