3

我曾经wasm-bindgen编写过一个非常基本的 JS/Wasm webapp,其中将灰度转换(用 Rust 编写)应用于 webapp 用户通过 an 上传<input type="file">并显示在<canvas>.

这样做,我必须将图像加载到 WebAssembly 内存空间中,对每个像素应用转换,然后将结果返回到内存空间中,以便 JS 处理显示:

import { memory} from "img-grayscale-wasm/img_grayscale_wasm_bg";
import {MyImage} from "img-grayscale-wasm"

//...

async function processImg(file, width, height){
  const canvas = document.getElementById("pixel-grayscale");

  var resp = await fetch(file.name)
  var bytes = await resp.arrayBuffer()

  const myImage = MyImage.new();
  const ptr = myImage.alloc(bytes.byteLength); 

  // Copy to memory space
  const imgArray = new Uint8Array(memory.buffer, ptr, bytes.byteLength);    
  imgArray.set(new Uint8Array(bytes));

  // transform img
  myImage.read_img(ptr, bytes.byteLength) 
  const grayScalePtr = myImage.to_grayscale(width, height)

  // read from memory space
  const arr = new Uint8ClampedArray(memory.buffer, grayScalePtr, width * height * 4);
  let imageData = new ImageData(arr, width);

  getContextFromCanvas(canvas, width, height).putImageData(imageData, 0, 0);
}

web-sys如果我使用crate 中定义的 web 的 API 绑定,我想我可以避免将东西来回复制到内存空间的整个过程,从fetch文件到灰度图片的显示。

这就是我感到困惑的地方:在性能方面,使用web-sys它的 web 的 API 绑定而不是全部用 JavaScript 进行是否有好处?好吧,我想有,但它在哪里?

4

1 回答 1

4

如果我对您的理解正确,那么您目前正在使用浏览器方法来回整理数据,以享受web-sys的荣耀。我有一些好消息和一些坏消息要告诉你。

好消息是,如果您的代码按照您所说的方式布局(这是一个片段非常方便的地方),您将获得一个内存副本。

现在,流程如下:

            1              2
         ======>        =====>       \
Browser         WebWorker      Rust   ||
         <======        <=====      <=/
            4              3

(优质的 ASCII 艺术,我知道)

1 是某种用户输入。2->3 是一个fetch循环。4是编组回来。

充其量,如果您的代码确实是这种结构,您可以通过将所有内容移至web-sys. 您不会摆脱 1 上的(相对最小的)数据副本,也不会摆脱 4 上的数据副本。

根据您正在去饱和的图像的大小以及您正在运行它的计算机,这可能会或可能不会带来性能提升。我没有研究过web-sys(这通常不是我的专业领域——我是一名嵌入式系统开发人员)的内部结构,所以我不能谈论 crate 本身的内部结构,但我假设fetch()是由浏览器完成的或完成的通过web-sys在性能上是相同的。

于 2018-12-24T23:50:17.507 回答