Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

运用Webassembly的一些心得 #15

Open
lsa2127291 opened this issue Nov 4, 2018 · 1 comment
Open

运用Webassembly的一些心得 #15

lsa2127291 opened this issue Nov 4, 2018 · 1 comment

Comments

@lsa2127291
Copy link
Owner

lsa2127291 commented Nov 4, 2018

前言

Webassembly作为2018年最受关注的技术之一,想必大家或多或少都了解过,但是真正使用过的人应该不多,一是因为这项技术还不太成熟,有太多坑要踩,二是因为少有场景需要用到。

而我尝试运用这项技术的原因是因为在项目开发中遇到了性能上的瓶颈,在努力尝试从算法层面优化后仍然无法满足需求。所以我想借助Webassembly从语言层面提升算法的性能,同时也抱着想要真正去研究实践一下这项新技术的心态。

简单介绍一下Webassembly

在知乎、掘金上面已经有很多很多对webassembly技术的介绍文章,所以我也没必要对它做太详细的介绍,想详细了解的同学可以看下WebAssembly这篇文章,讲的非常不错,也可以直接上官网了解。

简单地说,Webassembly就是一项将代码转换机器语言的技术,它不是一种直接的机器语言,但可以把它看是一种抽象出来的虚拟的机器语言,浏览器最终会把Webassembly语言编译成真正机器语言,并且只需要很低的成本。所以通过预先将代码编译成webassembly语言极大地减少了浏览器编译的成本,从而大幅提升代码运行速度。

如何编写Webassembly语言

编写webassembly有两种思路,一种是使用webassembly的文本格式(wat)直接编写,另一种利用是使用其他语言进行转换,介于wat是类似于汇编这种难以进行复杂编程的低级语言,所以大部分开发者都会选择第二方式,使用高级语言进行开发。理论上来说能够转换为llvm字节码的语言都能被编译成Webassembly语言,就我所了解目前对转换支持的比较好的语言有C\C++、Rust以及AssemblyScript。
C\C++这门语言就不用我介绍了,大家都太熟悉,同时也官方推荐的转换语言,一般刚接触webassembly的人都会使用C\C++作为转换语言。要了解如何由C\C++转向webassembly,就必须了解emscripten,这是最早也是最成熟的C\C++转webassembly工具,通过它的转换你不仅能够得到编译后的wasm文件,还帮你生成了对应的调用该wasm文件的js,运行所需要的环境也一并配置好了。在我们用C\C++编写比较复杂的程序时,在浏览器中运行所需要配置的环境也是非常复杂的,而emscripten这个特性让我们不需要费心去配置这些环境(比如内存分配,全局变量初始化等),所以非常有必要使用和学习它。

Rust是一门函数式风格的语言,语法简洁且上手容易,同时emscripten也支持rust转到webassembly,具体使用教程可以参考前端高性能计算之三:Rust -> asm.js & webassembly,这篇文章。所以其向webassembly的转换也非常方便,不用过多考虑环境配置问题,加上比C\C++支持跟多高级的语言特性,未来可能成为主流的转换语言。Rust的官网对它的语法有非常详细清晰的介绍,大家可以直接通过官网学习这们语言。

AssmblyScript的语法与TypeScript基本一致,可以看作是由TypeScript编译到webassembly,很适合前端工程师使用,但是目前支持还不是特别完善。它的git上提供了如何使用的说明,并附带了一些使用的例子,感兴趣的同学可以去了解一下。

不同语言转换到wasm的性能

很多刚入门的人,都因此会对webassembly产生一个错误的认识,就是认为webassembly之所以快是因为它由C转过来的,因为C的性能高所以webassembly的性能才好,如果换作其他语言的性能就会下降。

其实这是错误的想法,实际上无论C或是Rust甚至是Ts编写的项目,它们都会被编译成wasm格式的文件再运行,所以实际上浏览器运行都是WebAssembly字节码,跟你之前用何种语言写并无直接关系。但是并非意味着不同语言转换成wasm格式运行速度都是一样的,受wasm对语言转换支持的成熟度的影响,语言转换后的实际运行速度确实有所区别。

为了了解不同语言转换到webassblely的真实速度,我在webassembly.studio对C、Rust和AssemblyScript这三种语言分别进行了速度测试,三种语言运算斐波拉切数列的表现如下图:

  • C的运行情况:

d6766515a9cdb3dc3218c6dbd446d31d

  • Rust的运行情况:

3dabd366f5a44924e04ef8ca51c1b804

  • AssemblyScript的运行情况:

fc3e9b15d4ed63d2d9e858663e3c3640

  • 直接使用Js运行的情况:
    37576421a9f46018fd1232ee7c3ba609

从上图中,不难看出C和Rust的运行速度大体相当大约是180-190ms完成,AssemblyScript的运行速度要慢很多,耗时为300ms左右,而直接运行无疑最慢耗时达到了400多ms。所以目前对TypeScript的转换还支持的不太好,性能劣势比较明显,希望开发AssemblyScript的团队能够继续努力提升一下转换后的效率,作为前端的我还是非常期待能够看到这项技术能够成熟起来。

总结

Webassmbly是具有革命性的技术,它大幅度提高了前端的性能,让前端运行复杂算法成为了可能,进一步挖掘出了前端的潜能。目前,我们团队已经把部分图像处理算法转换到了webassembly,效果非常可观,平均性能提高了5到10倍,也不用再采用牺牲图像精度的方式去换取性能了。正是有了Webassembly,让前端体验逐步逼近客户端变成了可能。而且目前我们还只是处于初步尝试阶段,还有很多优化的空间,同时官方浏览器也在逐步优化Webassembly的性能,所以Webassembly未来的潜力真的不敢想象,非常值得我们去好好学习和探索。

@lsa2127291 lsa2127291 reopened this Nov 4, 2018
@MaxGraey
Copy link

MaxGraey commented Nov 4, 2018

  1. AssemblyScript fib(38): https://webassembly.studio/?f=hxvft8zztij
    Result: 351ms

  2. Rust fib(38): https://webassembly.studio/?f=h0q4tztjq85
    Result: 340ms

  3. C fib(38): https://webassembly.studio/?f=1ecrbz5uu5ek
    Result: 337ms

Unlike C and Rust, AssemblyScript does not use optimization by default so needs to be enabled in gulpfile.js inside asc.main as -O3 flag

More real benchmarks:

  1. https://github.com/AssemblyScript/assemblyscript/tree/master/examples/n-body
  2. using WebAssembly mapbox/mapbox-gl-js#4835 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants