javascript - 使用 Emscripten C++ Web Worker 高效传输大型数组 : which JavaScript design is better?

标签 javascript c++ three.js web-worker emscripten

我有一个 Emscripten C++ Web Worker,哪种设计可以更有效地将大数据传输到 JavaScript 程序?

因为网络 worker 做 clone()和序列化,通过web worker消息系统中转,这里有一些开销。还需要一些代码将 C++ 端的结果数据从 HEAP32 转换为 JavaScript 数组 ( C -> JS )。

高效是指哪种设计更快,即哪种设计触发更少 newgc() (构造和销毁 JS 对象)。我的 Web Worker 使用一个用 C++ 编写的核心函数,它返回大数组(两个数组 float[V][3]int[N][3],N=V=10000。它将用于更新 ThreeJS 几何图形,并将调用数十个在网页上长时间运行数千次。除了速度慢之外,这还可能导致浏览器变慢、卡住或崩溃。

  1. 使用 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。
  2. 使用使用 -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。
  3. 同样是一个 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/

相关文章:

c++ - LuaBridge 回调(将 lua 函数传递给 c++)

javascript - Three.js 如何确保模型加载后加载其他 javascript 文件

javascript - 使用 JQuery/Javascript 对单个更改事件执行多个操作

java - 根据用户提示延长 session

javascript - 让 NextJS 图像组件和 @svgr/webpack 一起玩得很好

javascript - 这个链接如何执行javascript

c++ - 滚动条Qt,无法滚动

c++ - 英特尔线程 C API

javascript - Three.js - 渲染问题 - 动画在晃动

javascript - Three.js TextGeometry 绘图问题