我有一个 Emscripten C++ Web Worker,哪种设计可以更有效地将大数据传输到 JavaScript 程序?
因为网络 worker 做 clone()
和序列化,通过web worker消息系统中转,这里有一些开销。还需要一些代码将 C++ 端的结果数据从 HEAP32 转换为 JavaScript 数组 ( C -> JS
)。
高效是指哪种设计更快,即哪种设计触发更少 new
和 gc()
(构造和销毁 JS 对象)。我的 Web Worker 使用一个用 C++ 编写的核心函数,它返回大数组(两个数组 float[V][3]
和 int[N][3]
,N=V=10000。它将用于更新 ThreeJS 几何图形,并将调用数十个在网页上长时间运行数千次。除了速度慢之外,这还可能导致浏览器变慢、卡住或崩溃。
- 使用 JS 编写 Web Worker,它导入使用 Emscripten 编译的 JS 代码。 缺点:这个选项似乎不可行,因为 web-worker 端需要导入编译后的 JS 文件。 数据交换:
C++ -> JS -> message(serialise) -> JS
.设计:(C++)JS <-WW-> JS
. 文件:core_mc_algorithm.cpp、worker.js、main.js。 - 使用使用
-s BUILD_AS_WORKER=1
编译的 C++ Web Worker ,在接收数据的主端写一些其他的C++代码,并在主端将结果从HEAP转换为JS:(由Emscripten处理的WebWorker data traser):优点:传输效率高,但是需要两次转换。 风险:在C++端,需要多次从 vector 复制到数组等。数据交换:C++ -> message(serialise) -> C++ -> JS
, 设计:(C++) <-WW-> C++(JS)
. 文件:worker.cpp、main.cpp、main.js。 - 同样是一个 C++ Web Worker,但是 Web Worker 函数直接由 JavaScript 中的主程序联系。 优点:转换/交换不会进行两次。 C++ 和 JS 之间没有单独的交换,这种转换是与 WW 序列化同时完成的。 风险:解码可能比较困难和困惑(协议(protocol)需要重新实现,本身需要多次转换,效率可能不是很高)。此外,交换实际上可能效率不高,实际上可能不会提高性能。 数据交换:
C++ -> message(serialise) -> JS
, 设计:(C++) <-WW-> JS
. 文件:worker.cpp, main.js .
我在 C++ 中有这段代码,我想将它作为 Web Worker 运行:
void produce_object (
REAL* verts_output, int number_of_vertices,
int* faces_output, int number_of_triangles ) {
// Run Marching cubes, which produces a vector<int> and a vector<float>.
// fills in the arrays verts_output[] with coordinates (size: 3*number_of_vertices),
// fill in faces_output[] with triangle vertex indices (size: 3*number_of_triangles ), using some numerical code which includes the Marching Cubes algorithm.
}
我需要以下 JavaScript 回调函数才能使用正确的参数进行调用。它在 HTML 文件中定义:
function update_mesh_geometry_callback (verts, faces) {
/* verts and faces are of type Float32Array and Int32Array of size (3*N) and (3*V). In this function they are used to create the following object, which is added to the scene.*/
var geo = new THREE.Geometry(verts, faces); // a subclass
scene.add(new THREE.Mesh(gro, mat, etc));
}
典型大小至少:number_of_vertices == 90000 = N,number_of_triangles == 8000 = V。
最佳答案
我相信您是在寻找可转让 Assets 。 Worker 在 postMessage
方法中有一个额外的参数:
https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage
Transferables 仅适用于 ArrayBuffer
,它们还会从消息传递线程中取消设置缓冲区,您必须牢记这一点,但对于您的情况而言,这似乎是一个完美的选择,因为它将避免完全复制。
这是您的 worker 中的玩具代码示例
var vertices = new Float32Array(100000);
var faceIndices = new Uint32Array(50000);
postMessage({vertices: vertices, faceIndices: faceIndices}, [vertices.buffer, faceIndices.buffer]);
您可以在此处阅读有关可转让 Assets 的更多信息: Using transferable objects from a Web Worker
关于javascript - 使用 Emscripten C++ Web Worker 高效传输大型数组 : which JavaScript design is better?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37867511/