使用Emscripten C Web Worker的大型阵列有效传输:JavaScript设计更好

Efficient transfer of large arrays with an Emscripten C++ Web Worker: which JavaScript design is better?

本文关键字:传输 JavaScript 更好 有效 阵列 Emscripten Web Worker 大型 使用      更新时间:2023-10-16

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

由于Web Worker进行clone()和序列化,要通过Web Worker消息系统传输,因此这里有一些开销。此外,还需要一些代码来将C 侧的结果数据转换为从HEAP32转换为JavaScript数组(C -> JS)。

通过高效,我的意思是哪种设计更快,即哪个设计导致触发较小的newgc()(构建和破坏JS对象)。我的网络工作者使用C 编写的核心函数,该功能返回大数组(两个阵列的float[V][3]int[N][3] n = v = 10000。网页上的长时间。除了缓慢,这也可能导致浏览器减速,冻结或崩溃。

  1. 使用JS编写一个Web Worker,该JS使用Emscripten导入JS代码编译。 cons :此选项似乎是不可能的,因为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处理的Webworkworker Data Traser): ProS :有效的转移,但需要进行两次转换。风险:在C 方面,它需要从向量到数组的多次复制等。数据交换: C++ -> message(serialise) -> C++ -> JS,设计:(C++) <-WW-> C++(JS)文件:worker.cpp,main.cpp,main.js。
  3. 再次是C Web Worker,但是Web Worker功能由JavaScript中的主程序直接联系。 PROS :转换/交换未完成两次。C 和JS之间没有单独的交换,此转换是在WW序列化的同时进行的。风险:解码可能很困难且混乱(协议将需要重新进化,这本身需要多次转换,这可能不是很有效)。同样,交易所可能实际上并不有效,实际上可能不会提高性能。数据交换: 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。

我相信您正在转移。工人在postMessage方法中具有额外的参数:https://developer.mozilla.org/en-us/docs/web/api/worker/postmessage

转移物仅适用于ArrayBuffer s,它们也可以解开"缓冲区消息"线程,您必须牢记这一点,但是就您而言,这似乎是一个完美的拟合,因为它将避免完全复制。

这是您在工作中将拥有的东西的玩具代码示例

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

您可以在此处阅读有关转移的更多信息:使用Web Worker的可转移对象