为什么说 WASM 是 Web 的未来?

为什么说 WASM 是 Web 的未来?

大家好,我是皮汤。过去两个月,我主要在研究WebAssembly(WASM)相关的内容,了解到WASM填补了Web一直以来缺失的部分:媲美原生的性能。对这方面有了一点心得,分享给大家。
了解WebAssembly的前世今生,这一致力于让Web更广泛使用的伟大创造是如何在整个Web/Node.js的生命周期起作用的,探讨为什么WASM是Web的未来?
在整篇文章的讲解过程中,你可以了解到WebAssembly原生、AssemblyScript、Emscripten编译器。
最后还对WebAssembly的未来进行了展望,列举了一些令人兴奋的技术的发展方向。
我在之前也撰写过深入了解WebAssembly使用细节和在浏览器里面调试WebAssembly代码的文章,感兴趣的同学可以点击链接阅读:
首先先来看一下JS代码的执行过程:
上述是MicrosoftEdge之前的ChakraCore引擎结构,目前MicrosoftEdge的JS引擎已经切换为V8。
整体的流程就是:
但其实我们平时写的代码有很多可以优化的地方,如多次执行同一个函数,那么可以将这个函数生成的MachineCode标记可优化,然后打包送到JITCompiler(Just-In-Time),下次再执行这个函数的时候,就不需要经过Parser-Compiler-Interpreter这个过程,可以直接执行这份准备好的MachineCode,大大提高的代码的执行效率。
但是上述的JIT优化只能针对静态类型的变量,如我们要优化的函数,它只有两个参数,每个参数的类型是确定的,而JavaScript却是一门动态类型的语言,这也意味着,函数在执行过程中,可能类型会动态变化,参数可能变成三个,第一个参数的类型可能从对象变为数组,这就会导致JIT失效,需要重新进行Parser-Compiler-Interpreter-Execuation,而Parser-Compiler这两步是整个代码执行过程中最耗费时间的两步,这也是为什么JavaScript语言背景下,Web无法执行一些高性能应用,如大型游戏、视频剪辑等。
通过上面的说明了解到,其实JS执行慢的一个主要原因是因为其动态语言的特性,导致JIT失效,所以如果我们能够为JS引入静态特性,那么可以保持有效的JIT,势必会加快JS的执行速度,这个时候asm.js出现了。
asm.js只提供两种数据类型:
其他类似如字符串、布尔值或对象都是以数值的形式保存在内存中,通过TypedArray调用。整数和浮点数表示如下:
ArrayBuffer对象、TypedArray视图和DataView视图是JavaScript操作二进制数据的一个接口,以数组的语法处理二进制数据,统称为二进制数组。参考ArrayBuffer。
而函数的写法如下:
上述的函数参数及返回值都需要声明类型,这里都是32位整数。
而且asm.js也不提供垃圾回收机制,内存操作都是由开发者自己控制,通过TypedArray直接读写内存:
从上可见,asm.js是一个严格的JavaScript子集要求变量的类型在运行时确定且不可改变,且去除了JavaScript拥有的垃圾回收机制,需要开发者手动管理内存。这样JS引擎就可以基于asm.js的代码进行大量的JIT优化,据统计asm.js在浏览器里面的运行速度,大约是原生代码(机器码)的50%左右。
但是不管asm.js再怎么静态化,干掉一些需要耗时的上层抽象(垃圾收集等),也还是属于JavaScript的范畴,代码执行也需要Parser-Compiler这两个过程,而这两个过程也是代码执行中最耗时的。
为了极致的性能,Web的前沿开发者们抛弃JavaScript,创造了一门可以直接和MachineCode打交道的汇编语言WebAssembly,直接干掉Parser-Compiler,同时WebAssembly是一门强类型的静态语言,能够进行最大限度的JIT优化,使得WebAssembly的速度能够无限逼近C/C++等原生代码。
相当于下面的过程:
无需Parser-Compiler,直接就可以执行,同时干掉了垃圾回收机制,而且WASM的静态强类型语言的特性可以进行最大程度的JIT优化。
我们可以通过一张图来直观了解WebAssembly在Web中的位置:
WebAssembly(也称为WASM),是一种可在Web中运行的全新语言格式,同时兼具体积小、性能高、可移植性强等特点,在底层上类似Web中的JavaScript,同时也是W3C承认的Web中的第4门语言。
为什么说在底层上类似JavaScript,主要有以下几个理由:
同时WASM也可以运行在Node.js或其他WASMRuntime中。
实际上WASM是一堆可以直接执行二进制格式,但是为了易于在文本编辑器或开发者工具里面展示,WASM也设计了一种“中间态”的文本格式,以.“wat或.wast为扩展命名,然后通过wabt等工具,将文本格式下的WASM转为二进制格式的可执行代码,以.wasm为扩展的格式。
来看一段WASM文本格式下的模块代码:
上述代码逻辑如下:
我们通过wabt将上述文本格式转为二进制代码:
当你安装好wabt之后,运行如下命令进行编译:
虽然转换成了二进制,但是无法在文本编辑器中查看其内容,为了查看二进制的内容,我们可以在编译时加上-v选项,让内容在命令行输出:
输出结果如下:
可以看到,WebAssembly其实是二进制格式的代码,即使其提供了稍为易读的文本格式,也很难真正用于实际的编码,更别提开发效率了。
因为上述的二进制和文本格式都不适合编码,所以不适合将WASM作为一门可正常开发的语言。
为了突破这个限制,AssemblyScript走到台前,AssemblyScript是TypeScript的一种变体,为JavaScript添加了WebAssembly类型,可以使用Binaryen将其编译成WebAssembly。
WebAssembly类型大致如下:
Binaryen会前置将AssemblyScript静态编译成强类型的WebAssembly二进制,然后才会交给JS引擎去执行,所以说虽然AssemblyScript带来了一层抽象,但是实际用于生产的代码依然是WebAssembly,保有WebAssembly的性能优势。AssemblyScript被设计的和TypeScript非常相似,提供了一组内建的函数可以直接操作WebAssembly以及编译器的特性.
内建函数:
然后基于这套内建的函数向上构建一套标准库。
标准库:
如一个典型的Array的使用如下:
可以看到AssemblyScript在为JavaScript添加类似TypeScript那样的语法,然后在使用上需要保持和C/C++等静态强类型的要求,如不初始化,进行内存分配就访问就会报错。
还有一些扩展库,如Node.js的process、crypto等,JS的console,还有一些和内存相关的StaticArray、heap等。
可以看到通过上面基础的类型、内建库、标准库和扩展库,AssemblyScript基本上构造了JavaScript所拥有的的全部特性,同时AssemblyScript提供了类似TypeScript的语法,在写法上严格遵循强类型静态语言的规范。
值得一提的是,因为当前WebAssembly的ES模块规范依然在草案中,AssemblyScript自行进行了模块的实现,例如导出一个模块:
导入一个模块:
一个大段代码、使用类的例子:
AssemblyScript为我们打开了一扇新的大门,可以以TS形式的语法,遵循静态强类型的规范进行高效编码,同时又能够便捷的操作WebAssembly/编译器相关的API,代码写完之后,通过Binaryen编译器将其编译为WASM二进制,然后获取到WASM的执行性能。
得益于AssemblyScript兼具灵活性与性能,目前使用AssemblyScript构建的应用生态已经初具繁荣,目前在区块链、构建工具、编辑器、模拟器、游戏、图形编辑工具、库、IoT、测试工具等方面都有大量使用AssemblyScript构建的产物:https://www.assemblyscript.org/built-with-assemblyscript.html#games
上面是使用AssemblyScript构建的一个五子棋游戏。
虽然AssemblyScript的出现极大的改善了WebAssembly在高效率编码方面的缺陷,但是作为一门新的编程语言,其最大的劣势就是生态、开发者与积累。
WebAssembly的设计者显然在设计上同时考虑到了各种完善的情况,既然WebAssembly是一种二进制格式,那么其就可以作为其他语言的编译目标,如果能够构建一种编译器,能够将已有的、成熟的、且兼具海量的开发者和强大的生态的语言编译到WebAssembly使用,那么相当于可以直接复用这个语言多年的积累,并用它们来完善WebAssembly生态,将它们运行在Web、Node.js中。
幸运的是,针对C/C++已经有Emscripten这样优秀的编译器存在了。
可以通过下面这张图直观的阐述Emscripten在开发链路中的地位:
即将C/C++的代码(或者Rust/Go等)编译成WASM,然后通过JS胶水代码将WASM跑在浏览器中(或Node.js)的runtime,如ffmpeg这个使用C编写音视频转码工具,通过Emscripten编译器编译到Web中使用,可直接在浏览器前端转码音视频。
上述的JS“Gule”代码是必须的,因为如果需要将C/C++编译到WASM,还能在浏览器中执行,就得实现映射到C/C++相关操作的WebAPI,这样才能保证执行有效,这些胶水代码目前包含一些比较流行的C/C++库,如SDL、OpenGL、OpenAL、以及POSIX的一部分API。
目前使用WebAssembly最大的场景也是这种将C/C++模块编译到WASM的方式,比较有名的例子有UnrealEngine4、Unity之类的大型库或应用。
答案是不会。
根据上面的层层阐述,实际上WASM的设计初衷就可以梳理为以下几点:
所以从初衷出发,WebAssembly的作用更适合下面这张图:
WASM桥接各种系统编程语言的生态,近一步补齐了Web开发生态之外,还为JS提供性能的补充,正是Web发展至今所缺失的重要的一块版图。
RustWebFramework:https://github.com/yewstack/yew
地址:https://github.com/emscripten-core/emscripten
下面所有的demo都可以在仓库:https://code.byted.org/huangwei.fps/webassembly-demos/tree/master找到
Star:21.4K
维护:活跃
Emscripten是一个开源的,跨平台的,用于将C/C++编译为WebAssembly的编译器工具链,由LLVM、Binaryen、ClosureCompiler和其他工具等组成。
Emscripten的核心工具为EmscriptenCompilerFrontend(emcc),emcc是用于替代一些原生的编译器如gcc或clang,对C/C++代码进行编译。
实际上为了能让几乎所有的可移植的C/C++代码库能够编译为WebAssembly,并在Web或Node.js执行,EmscriptenRuntime其实还提供了兼容C/C++标准库、相关API到Web/Node.jsAPI的映射,这份映射存在于编译之后的JS胶水代码中。
再看下面这张图,红色部分为Emscripten编译后的产物,绿色部分为Emscripten为保证C/C++代码能够运行的一些runtime支持:
值得一提的是,WebAssembly相关工具链的安装几乎都是以源码的形式提供,这可能和C/C++生态的习惯不无关系。
为了完成简单的C/C++程序运行在Web,我们首先需要安装Emscripten的SDK:
如果安装成功,上述的命令运行之后会输出如下结果:
让我们准备初始代码:
在main.c中加入如下代码:
然后使用emcc来编译这段C代码,在命令行切换到webassembly/hello_world目录,运行:
上述命令会输出两个文件:a.out.js和a.out.wasm,后者为编译之后的wasm代码,前者为JS胶水代码,提供了WASM运行的runtime。
可以使用Node.js进行快速测试:
会输出”hello,world!”,我们成功将C/C++代码运行在了Node.js环境。
接下来我们尝试一下将代码运行在Web环境,修改编译代码如下:
上述命令会生成三个文件:
Emscripten生成代码有一定的规则,具体可以参考:https://emscripten.org/docs/compiling/Building-Projects.html#emscripten-linker-output-files
如果要在浏览器打开这个HTML,需要在本地起一个服务器,因为单纯的打开通过file://协议访问时,主流浏览器不支持XHR请求,只有在HTTP服务器下,才能进行XHR请求,所以我们运行如下命令来打开网站:
打开网页,访问localhost:3000/main.html,可以看到如下结果:
同时开发者工具里面也会有相应的打印输出:
我们成功的将C代码跑在了Node.js和浏览器!
本文仅仅列举了一些WebAssembly当前的一些主要应用场景,包含WebAssembly的高性能、轻量和跨平台,使得我们可以将C/C++等语言运行在Web,也可以将桌面端应用跑在Web容器。
但是这篇文章没有涉及到的内容有WASI,一种将WebAssembly跑在任何系统上的标准化系统接口,当WebAssembly的性能逐渐增强时,WASI可以提供一种恰是可行的方式,可以在任意平台上运行任意的代码,就像Docker所做的一样,但是不需要受限于操作系统。正如Docker的创始人所说:
“如果WASM+WASI在2008年就出现的话,那么就不需要创造Docker了,服务器上的WASM是计算的未来,是我们期待已久的标准化的系统接口。
另一个有意思的内容是WASM的客户端开发框架如yew,未来可能将像React/Vue/Angular一样流行。
而WASM的包管理工具WAPM,得益于WASM的跨平台特性,可能会变成一种在不同语言的不同框架之间共享包的首选方式。
同时WebAssembly也是由W3C主要负责开发,各大厂商,包括Microsoft、Google、Mozilla等赞助和共同维护的一个项目,相信WebAssembly会有一个非常值得期待的未来。
我是皮汤,一个酷爱编程,乐于分享的小伙子,下期见~
❤️/感谢支持/
以上便是本次分享的全部内容,希望对你有所帮助^_^
喜欢的话别忘了分享、点赞、收藏三连哦~
欢迎关注公众号**程序员巴士**,来自字节、虾皮、招银的三端兄弟,分享编程经验、技术干货与职业规划,助你少走弯路进大厂。

主题测试文章,只做测试使用。发布者:最新稳定辅助网,转转请注明出处:https://www.744broad.com/15374.html

(0)
上一篇 2023年3月7日 上午2:25
下一篇 2023年3月7日 上午2:32

相关推荐

  • 值得深入了解的物联网编程语言,你熟悉几款呢?

    值得深入了解的物联网编程语言,你熟悉几款呢? 在物联网的带动下,制造业正迎来新一轮变革浪潮,云计算、大数据、人工智能等新技术正在加速与工业领域的全方位融合。纵观全球市场,工业4.0趋势所向,中美德各有千秋,因此,也形成了不同的局面,制造领域中,企业正在寻找新的经济增长点。物联网物联网开发项目目前正在全球范围的诸多企业当中如火如荼地展开。新型硬件平台的出现让工…

    RUST资讯 2023年3月11日
    20
  • 腐蚀Rust画面怎么设置 腐蚀Rust画面设置优化教程

    腐蚀Rust画面怎么设置 腐蚀Rust画面设置优化教程 图像质量1~3为一个大档4~5是一个大档4以上你在游戏里面的画面会显示更多细节的东西大家可以从下面图片的半自动机瞄下面的图案来看清3档一下和4档以上的差距第一个画线选项PARTICLEQUALITY:这是粒子效果这个是对于游戏里枪的火光和一些光源的显示就好比你打枪的火光一样但是建议开低或者彻底关闭因为当…

    RUST资讯 2023年2月25日
    40
  • 焊接时如何防止识别未焊透和未熔合?

    焊接时如何防止识别未焊透和未熔合? 未焊透对焊接结构的直接危害是降低了焊接接头的承载截面积和力学性能。未焊透引起的应力集中远比强度降低更有害。承受冲击载荷、交变载荷、低温工作或应力腐蚀的焊接结构,会导致脆性断裂。未熔合会降低了焊接结构的有效厚度,而且在使用过程中容易在未熔合的工件边缘造成应力集中,应力集中向外扩散形成裂纹,会导致整个焊缝开裂。Thedirec…

    RUST资讯 2023年2月26日
    30
  • 《生死六分钟》一百一十一集 有一座古老的豪宅。在新奥尔良

    《生死六分钟》一百一十一集 有一座古老的豪宅。在新奥尔良 安德森一家住在阿拉斯加的首府Juneau,家里的成员有勇敢理智的爸爸JAMES,和蔼可亲的妈妈MONICA,喜欢科学的哥哥CYRUS,和喜欢调皮捣蛋的妹妹BIRDIE,可是,他们的平静生活被一件事打断了。。。111-T1INT.CONVENIENCESTORE-NIGHTPickupBirdieand…

    RUST资讯 2023年2月13日
    80
  • 精品推荐—稀有银币,绿漆古铜币

    精品推荐—稀有银币,绿漆古铜币 古钱币极具观赏性与历史价值,因此古钱币如同其他古玩一样被藏家们所青睐。中国最早的机制洋式银元为光绪年间的“光绪元宝”,俗称“龙洋”,因钱币背面一般铸有龙纹而得名。珍稀古钱币是货币历史的实物,由于早已不在流通领域,留存下来的亦少之极少,更是历史的见证。光绪元宝为清代货币,当时正值洋务运动时期,这股思潮也影响到了铸币业,两广总督张…

    RUST资讯 2023年2月28日
    50
  • Rust语言入门教程 引用循环与内存泄漏

    Rust语言入门教程 引用循环与内存泄漏 Rust的内存安全性保证使其难以意外地制造永远也不会被清理的内存(被称为内存泄漏(memoryleak)),但并不是不可能。与在编译时拒绝数据竞争不同,Rust并不保证完全地避免内存泄漏,这意味着内存泄漏在Rust被认为是内存安全的。这一点可以通过Rc和RefCell看出:创建引用循环的可能性是存在的。这会造成内存泄…

    RUST资讯 2023年2月21日
    90
  • 2016开发者调查 JavaScript语言最受欢迎

    2016开发者调查 JavaScript语言最受欢迎 【天极网IT新闻频道】美国知名开发者问答论坛StackOverflow今年搜集了来自全球173个国家,近6万份开发者问卷完成了2016年开发者调查报告。报告显示JavaScript再度蝉联今年最受欢迎的程序开发语言、Mozilla系统语言Rust变成开发者的最爱、而最让开发人员头痛的要属VisualBas…

    RUST资讯 2023年2月15日
    100
  • CWE 4.3:强化你的数据自我保护能力

    CWE 4.3:强化你的数据自我保护能力 ​​​​​​​​​​​​​​​【摘要】如何通过软件自动的检查法规中涉及的数据保护,新版的CWE4.3给出了一个解决途径。用12月初在深圳参加的”全球C++及系统软件技术大会”里C++之父Bjarne讲的一个故事,致敬一下这位大能。由于疫情,Bjarne不能亲自来到会场,只能通过视频的方式和大家…

    RUST资讯 2023年2月17日
    60
  • 工业芳烃铜片腐蚀检测仪 操作直观简单

    工业芳烃铜片腐蚀检测仪 操作直观简单 主题内容与适用范围本标准规定了试样在加热回流条件下,对铜片腐蚀性定性试验的方法。本标准适用于工业芳烃。注意:本标准所用的样品和溶剂是有毒的,应避免吸入体内和接触皮肤;它们易燃,操作时应遵守相应的安全和保健措施。引用标准GB466铜分类GB/T5096石油产品铜片腐蚀试验法GB5231’加工铜化学成分和产品形状GB/T11…

    RUST资讯 2023年2月26日
    40
  • Linux下 Alluxio 的编译和运行

    Linux下 Alluxio 的编译和运行 第一次接触分布式项目,还是在Linux下编程,确实和Windows下编程有一点点不一样。没有一点点防备,就让我了解到不能用在windows上运行的代码,以及除了web开发之外的开发。熟悉了以前在Windows下的开发,用IDEA工具开发,点build编译项目(之前一直翻译成构建项目),点run运行项目,有时甚至都不…

    RUST资讯 2023年2月19日
    90
关注微信