华人澳洲中文论坛

Webassembly 实战

[复制链接]

2022-9-1 07:28:09 59 0

配景
名目中使用Canvas绘图,有一个笔刷功用,后端会给前端mask编码的数据,前端需求转成ImageData,能力绘制到Canvas上,这个转换至关耗时,以后是放在worker里计算,而后再前往ImageData渲染,当mask得多、很大的状况时,仍是会存在机能问题,一方面内存占用过大、一方面是履行时间太长。有无优化的空间?
比来看了一本对于Rust的书籍,想看一下基于Rust的Webassembly机能咋样,因而首先想到了mask的功用,先在这个功用试验一下,假如还不错,能够推行到其它场景,Canvas的得多底层操作都对比耗机能,假如能用wasm,乃至能够媲美原生客户端。此外未来产品也有可能推出客户端版本,或许基于Tauri的客户端版本也是一种选择,能够做一些技术贮备。
数据比较
通过苦楚的重构(Rust的语法真的太难了...),终于把mask转换的代码重构为wasm,并接入Vimo,看看一下数据如何:
形容
mask示例
worker机能
wasm机能
阐明
mask数量少、尺寸小




均匀:30ms
request耗时很高




均匀
mask尺寸很小的状况下,wasm的机能远远超过worker
mask数量多、尺寸大




三张图片,分别是:8155ms、2215ms、5309ms


三张图片,分别是:1606ms、373ms、783ms
mask数量多,尺寸也较大的状况下,wasm的机能是worker的4倍以上
mask尺寸大




同一张图片测试两次,均匀15000ms


同一张图片测试两次,均匀2250ms
mask尺寸超大的状况,wasm机能是worker的6倍
初步论断
转换机能:mask的机能在各种场景下都优于worker,机能最少晋升4倍以上,当mask很小时,机能是worker的30倍。
内存占用:内存占用不太好测试,用阅读器的Performance简略测试了一下,wasm的内存占用也比worker的小。
技术调研Worker 计划
将一个mask绘制到界面次要有两个步骤,这两个步骤都对比耗时,第一步是转换,将mask转成imageData,这一步是纯计算的,会放在worker外面,第二步是绘制,下列只关注转换这一步,第二步暂不关注(虽然它也很慢,还存在可优化的空间)。
因为worker是异步的,转化分为三个小步骤:
postMessage to worker ,这一步将需求转换的mask传给workerGenerate ImageData,这一步将mask转成ImageData,像素点操作,机能问题次要泛起在这一步骤postMessage to brower,这一步将转换好的ImageData传回给阅读器,而后就能绘制啦!


与worker交互,数据需求序列化、反序列化,当对象很大时,是很耗机能的,如下的例子就能充沛阐明,不论mask多大,postMessage to worker这一步会花不少时间,实际上mask转行是很快(1毫秒摆布),但往返的传输就很慢了


Webassembly 摹拟worker计划
重构为Wasm的初版版本,我选择跟worker相似的计划,只是用rust完成罢了,也是分三个小步骤:
mask_data to JsValue,与wasm交互,动静一样需求序列化Generate ImageData,mask转换,跟worker逻辑同样image_data to JsValue,将image_data序列化后给到阅读器


论断:实际测试上去,最初一步将image_data序列化很耗时,整体时间乃至比worker的还慢,所以此计划废弃了。
Webassembly 同享内存计划
数据序列化和反序列化通常很耗时,那有无计划绕过它?谜底就是同享内存,这也是wasm保举的做法之一,与wasm交互时,数据只要一份且存在wasm的memory对象中,阅读器间接读取wasm中内存数据并渲染,无需额定空间,三个小步骤
Write mask to share memory,将需求转换的数据写入wasm内存,再也不经过序列化传给wasm了Generate ImageData,从内存读取mask数据并转成ImageData,并将ImageData写入share memory,再也不经过序列化传给阅读器Read ImageData from share memory,阅读器间接读取wasm内存,并绘制,无需再结构对象


阐明:下面的测试数据就是基于这个计划完成的,实际上还有优化空间,内存还能够优化一下,时间瓜葛就没做了。
Webassembly 多线程计划
下面的计划还没彻底利用wasm的劣势,mask转换是能够并发的,那末能否用并发去转换mask呢?
wasm原生还不反对异步(据说有方案反对),想在阅读器跑多线程,目前只要worke能做到了,咱们能够跑多个woker,在每个worker外面再去调用wasm,这样在mask数量得多的状况下,利用多线程,机能又能晋升不少


阐明:名目还未完成,github上有一个使用wasm + woker做多线程的例子,能够关上去体验下:http://github.com/jsdw/wasm-fractal
One More Thing
以后是把一切mask转成imageData之后再一致渲染(draw)的,当mask得多、很大的时分,有可能会由于内存占用过量而致使阅读器卡死,对比好的解决计划是分片渲染,也即边转换、边绘制,这样用户体验也会好得多(虽然整体时间其实不会增加)。重构后的wasm计划,反对分片渲染会更灵敏,由于它是每一个个mask独自转换,能够灵敏管制,内存及时回收,阅读器不易崩掉(以后的worker是批量转换的)
除了mask这一步能够用wasm完成以外,绘制是不是也能够呢,我以为只有波及到少量像素点操作的,应该均可有用wasm,固然啦,这所有还要斟酌开发本钱。
参考
Setup - Rust and WebAssembly入门 Rust 开发 WebAssemblyrustwasm.github.io

发表回复

您需要登录后才可以回帖 登录 | 立即注册

返回列表 本版积分规则

:
注册会员
:
论坛短信
:
未填写
:
未填写
:
未填写

主题25

帖子36

积分171

图文推荐

  • 撞穿学校栅栏害死十一岁男孩的司机不必坐牢

    一位女司机撞穿学校栅栏、害死了11岁男孩,被罚20

  • 全科医生正告花粉症时节正在好转

    全国各地的全科医生正告春季的开端标记着花粉症时

  • 新西兰总理:出世在新西兰的新纳粹Thomas S

    新西兰总理拉克森称新纳粹Thomas Sewell是坏人,

  • 新州护士和助产士承受暂时加薪3%的前提

    新州护士和助产士投票承受政府提出的暂时加薪3%以

  • 新纳粹份子如何利用“普通父母”的掩护在反

    星期天,新纳粹份子在反移民集会开端前大约一个小