使用Emscripten C ++ Web Worker高效传输大型数组:哪种JavaScript设计更好?

时间:2016-06-16 19:08:44

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

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

由于Web工作者执行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工作者方需要导入编译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 :( WebWorker数据处理器由Emscripten处理):优点:高效转移,但需要两次转化。 风险:在C ++方面,它需要从向量到数组等多次复制。数据交换: C++ -> message(serialise) -> C++ -> JS,设计:(C++) <-WW-> C++(JS)文件:worker.cpp,main.cpp,main.js。
  3. 同样是C ++ Web Worker,但是直接通过JavaScript中的主程序联系Web worker函数。 优点:转化/交换不会进行两次。 C ++和JS之间没有单独的交换,这种转换是在WW序列化的同时完成的。 风险:解码可能很困难而且很混乱(协议需要重新实现,这本身需要多次转换,这可能效率不高)。此外,交换可能实际上不是有效的,并且可能实际上不会提高性能。 数据交换: C++ -> message(serialise) -> JS,设计:(C++) <-WW-> JS文件:worker.cpp,main.js。
  4. 我在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。

1 个答案:

答案 0 :(得分:1)

我相信你是在转会之后。 Worker在postMessage方法中有一个额外的参数: https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage

Transferables仅适用于ArrayBuffer s,它们也取消了来自消息传递线程的缓冲区,你必须牢记这一点,但对于你的情况,这似乎是一个完美的契合,因为它将避免完全复制。

这是一个玩具代码示例,说明您在工作中的内容

var vertices = new Float32Array(100000);
var faceIndices = new Uint32Array(50000);
postMessage({vertices: vertices, faceIndices: faceIndices}, [vertices.buffer, faceIndices.buffer]);

您可以在此处阅读有关可转让的更多信息: Using transferable objects from a Web Worker