ad208三国

 找回密码
 加入
搜索
热搜: 活动 交友 discuz
查看: 809|回复: 4

wasm面向Web的二进制格式WebAssembly,是可移植、高性能、低级别的虚拟机

[复制链接]
发表于 2023-7-12 12:34:40 | 显示全部楼层 |阅读模式

pc2g,电脑好游戏 WebAssembly是一种面向Web的二进制格式,不是一种编程语言,它是一种可移植、高性能、低级别的虚拟机。

它是由W3C(万维网联盟)设计的一种新型的Web标准,旨在通过在Web浏览器中运行高性能的本机二进制代码,提供更快速、更安全的Web应用程序。
它可以由多种编程语言(如C/C++、Rust、Go、Java,Typescript等)编译生成。WebAssembly代码可以在任何支持WebAssembly的环境中运行,如Web浏览器、Node.js等。WebAssembly可以通过JavaScript调用,并且还可以与JavaScript共享数据和调用函数。

对于网络平台而言,WebAssembly 具有巨大的意义——它提供了一条途径,以使得以各种语言编写的代码都可以以接近原生的速度在 Web 中运行。在这种情况下,以前无法以此方式运行的客户端软件都将可以运行在 Web 中。

WebAssembly 被设计为可以和 JavaScript 一起协同工作——通过使用 WebAssembly 的 JavaScript API,你可以把 WebAssembly 模块加载到一个 JavaScript 应用中并且在两者之间共享功能。这允许你在同一个应用中利用 WebAssembly 的性能和威力以及 JavaScript 的表达力和灵活性,即使你可能并不知道如何编写 WebAssembly 代码。

WebAssembly(缩写为 wasm)是一种使用非 JavaScript 代码,并使其在浏览器中运行的方法。这些代码可以是 C、C++ 或 Rust 等。它们会被编译进你的浏览器,在你的 CPU 上以接近原生的速度运行。这些代码的形式是二进制文件,你可以直接在 JavaScript 中将它们当作模块来用。

官网https://webassembly.org/
中文手册https://developer.mozilla.org/zh-CN/docs/WebAssembly
英文手册https://webassembly.org/getting-started/developers-guide/

Git仓库的源码
https://github.com/wasm3/wasm3
https://github.com/aduros/wasm4

游戏演示https://wasm4.org/play/
网络多人对战https://wasm4.org/blog/release-2-4-0
 楼主| 发表于 2023-7-12 12:51:03 | 显示全部楼层
5分钟看懂WebAssembly
https://zhuanlan.zhihu.com/p/158042212
20分钟上手 webAssembly - 掘金
https://juejin.cn/post/6844903661982728200
WebAssembly入门
https://zhuanlan.zhihu.com/p/278028242
前端展望-WebAssembly(wasm)技术入门
https://juejin.cn/post/6963175242613293086
WebAssembly完全入门——了解wasm的前世今身
https://zhuanlan.zhihu.com/p/68048524
快 11K Star 的 WebAssembly,你应该这样学
https://juejin.cn/post/7013286944553566215

将Typescript编译成WebAssembly
https://juejin.cn/post/7206297124941054008
使用 Docker 和 Golang 快速上手 WebAssembly - 知乎
https://zhuanlan.zhihu.com/p/435852919
Docker + Wasm = 王炸
https://blog.csdn.net/2301_77463738/article/details/131490340

从零开始创建WebAssembly 游戏_wasm 开发一个小游戏
https://blog.csdn.net/qq_27217017/article/details/123604677
wasm编译mame游戏到h5中_linux内核控的博客
https://blog.csdn.net/leafrenchleaf/article/details/106880622


基于WebAssembly开发网页端
https://zhuanlan.zhihu.com/p/162082688?utm_id=0
浏览器中加载wasm模块到JavaScript
https://blog.csdn.net/u012151242/article/details/131532888

这群 WebAssembly 大佬创业失败了:有时从 JS 迁移到 Wasm 并不值当?
https://www.infoq.cn/article/lx1NyUdpRJ03XTuU8x4J
 楼主| 发表于 2023-7-12 13:07:54 | 显示全部楼层
WebAssembly在大型项目中的应用

    Tensorflow.js:是的,就是那个Tensorflow,那个是把AI和ML带给JS开发人员的库,在添加了WASM后端支持后,Tensorflow一直致力于实现更多的模型,效果如何?与纯JS版本相比,这些模型性能平均提高了10倍。
https://blog.tensorflow.org/2020 ... -tensorflow-js.html

    Unity:另一个很牛很牛的技术大厂牌,最最重要的游戏开发引擎之一,它能够将你的项目导出与Web相兼容。从2018年开始,该过程通过编译为WebAssembly来完成——在Unity上的应用成为了高效利用WASM技术的一个强大示范;游戏开发人员不再需要为Web做代码编译、更不需要去摆弄JS,他们只需要专注于编写用于支持游戏运行那部分代码,然后,其它交由编译过程去处理并完成。
https://livehelp.unity.com/artic ... zhi-chi-webassembly
Unity WebGL
https://youtu.be/rIyIlATjNcE
Unreal引擎
https://www.youtube.com/watch?v=TwuIRcpeUWE


    AutoCAD web app:你并没看错,Autodesk的web cad应用确实已部分被“移植”,它们使用了基于WASM编译的C ++代码。对于WASM来说,在AutoCAD上的应用是其所迈出的重要和极具潜力的一步,因其重新利用了为完全不同的平台编写的代码(且是用完全不兼容的语言)使用到现代浏览器中。
https://www.autodesk.com/product ... NCED&quantity=1

    Google Earth:不是所有人都了解,至今Google Earth已经发展15年,它曾经是桌面应用程序,现在有了WASM,产品团队通过把部分旧代码编译为WASM(类似于Autodesk在其CAD应用中所做)并将其部分移植到了Web中,这是个不小的成就,无疑,这又给WASM“履历”中加分了。
https://earth.google.com/web/

    Blazer:ASP.NET框架的一项功能使我们可以构建直接在浏览器上运行的各种交互式UI;通过Web Assembly释放的“魔法”,.NET代码可以直接在浏览器上执行,这样我们可以充分利用C#编写的服务器端代码(对于Web UI)的全部优势。
https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor

    yew:是否曾考虑过将Rust用于Web应用程序?现在,我们要感谢Yew和WebAssembly给我们带来的多一种“可能性”——你不仅可以将Rust用于UI,而且此框架还提供了一个多线程环境来工作。该项目尚未投入生产环节,但是无论你是对Rust很狂热还是有兴趣,都可以持续关注下。
https://github.com/yewstack/yew




WebAssembly的几个开发工具

    AssemblyScript。支持直接将TypeScript编译成WebAssembly。这对于很多前端同学来说,入门的门槛还是很低的。
https://github.com/AssemblyScript/assemblyscript

    Emscripten。可以说是WebAssembly的灵魂工具不为过,上面说了很多编译,这个就是那个编译器。将其他的高级语言,编译成WebAssembly。
https://github.com/emscripten-core/emscripten

    WABT。是个将WebAssembly在字节码和文本格式相互转换的一个工具,方便开发者去理解这个wasm到底是在做什么事。
https://github.com/WebAssembly/wabt
 楼主| 发表于 2023-7-12 13:24:31 | 显示全部楼层
以下文字转载自https://www.zhihu.com/question/362649730/answer/2354248894 原文有图,排版有些乱,整理文字版如下,如有错漏还请查看原文

WebAssembly武功秘籍——C++库集成的完整通用路线图

    最近有同事因为需要将公司自研的一些C++音视频能力底层通用库编译到前端同构,找笔者询问WASM编译的入门难度、编译思路、预期人力投入等估计,因此总结一个整体思路路线图,供大家参考。

   钻研WebAssembly(简称WASM)武功,首先是为了集成其他语言的完整生态,让已有成果畅通无阻地直接跑在浏览器里,起到拓展前端整体能力的作用。这门功夫很新,还在发展阶段,受众很广,但传教做得不好,没多少新手友好的教程流传在世间。

configure文件通常是由Autotools中autoconf生成的,是最常见的C++项目组织方式,在WASM领域可以视为正统的代表。WASM对其有最完备的支持,大多数情况,只需要把原来configure xxx变成emconfigure configure xxx即可,一个命令完成

https://emscripten.org/docs/compiling/Building-Projects.html]https://emscripten.org/docs/compiling/Building-Projects.html

http://xn--km-w62c181gba2093aca91du7b/]FFmpeg.wasm

完整的C++项目可能很庞大、很复杂,理不清楚代码间的依赖关系;但我们实际需求用到的或许只是项目中的某一个功能。
这个时候我们要明确告诉WASM我们需要的是哪个函数,以及相关的头文件、源文件目录,WASM会自动忽略其他部分并打包好我们要的特定功能,有“四两拨千斤”的效果。找到这个关键函数对于初期习武者还是有些困难。
假如不知道我们需要的功能函数具体位置,又想使用怎么办?很简单,告诉WASM我们需要整个项目的main函数(入口函数),它会自己帮你打包好的。

https://emscripten.org/docs/comp ... manually-using-emcc

http://xn--km-wu2cp04gba2093aca91du7b/]SoundTouch.wasm


cmake、bazel等主流构建技术每种都有自己的独特设计,WASM为每一种都做了专门的兼容,保持原有编译链不变。编译时需要严格按照当前构建技术对应的规则去做,不能混淆。
https://github.com/emscripten-co ... rm/Emscripten.cmake

https://docs.bazel.build/version ... olchain-config.html


对于没有组织的C++项目:
主线函数和其依赖的头文件、源文件目录,告知WASM,但这种方法需要深厚的内功,难度不小。
借助Autotools手动给它生成一个configure文件,这样做难度降低了一些,时间换空间。
尝试用cmake之流完整重组项目。但是项目作者都没完成的事,我们自然不能保证我们就能完成。轻易不要尝试。

  • 为了避免主观地冠名不同C++项目会挨骂,这里还是要解释一下:区分C++项目的定位并根据特征冠名,不是为了讨论出个三六九等,而是抓住关键特征,方便有针对性地处理,万事别太较真~

    WASM编译,首先需要确定目标主机,也就是编译出来的二进制程序所执行的主机格式。如果主机格式选错,后面一切免谈。
    简单来说,有generic-gnu直接选,没有就选x86_64-linux、x86_64-gnu、i686-gnu之流。
    从根本上说,要确定执行代码编译的主机(自己的主机),和编译出来的二进制程序所执行的主机(一般是自己主机)是否一致。如果不一样,就要用到交叉编译。这在WASM中很常见。
    https://www.gnu.org/software/aut ... 02dCompilation.html

    WASM编译中,许多C++库不会显式传递Linux环境变量,而是隐式调用,编写编译命令的时候是没有感知的。这种隐蔽所带来的错误是最难在编译前发现的。为了避免这种错误,无论具体的某个C++程序是否用得到,都建议提前设置这些环境变量,如有问题再具体去改:  
    1:通用预设环境变量
      
    https://www.gnu.org/software/aut ... tion-Variables.html
      
    https://github.com/sekrit-twc/zimg/issues/167
    zimg库对PTHREAD_CFLAGS的隐式调用

    CPU一直往更多核的方向发展是好是坏,暂时没有统一定论,但并行计算的性能是有目共睹的,爱与不爱,都要用。
    在WASM编译中,为特定C++库打开并行开关的方法差异比较大。
    低难度版的是这个库本身已经提供了--enable-pthreads、--enable-multithreads这样的参数,编译时直接用就行
    中难度版的是这个库没有显式的并行开关,但在隐式调用pthreads相关环境变量时会进行很缜密的检查,包括
    pthreads”、“-Kthread”、“-pthread”、“-mthreads”等等,不会因为编译环境的不同而漏掉。只要在编译前按照【逍遥子】的指导设置过环境变量,就能自动打开并行开关。  

    2:各种并行环境变量,顺序严格从前到后
    高难度版的是这个库原来对并行的支持就没有或不完善。下文专门用来解决这个问题。
    https://github.com/sekrit-twc/zi ... d3d399da2c68335b9e6
    zimg库补充对PTHREAD_CFLAGS的检查和使用

    我们现在想解决的一些编译难题,C++库的作者也会想。其中一些作者会把他的解决方案凝聚成独立参数,放在configure或Readme中加以说明,这就是他的武功秘籍了。每个库中被作者单独提炼出来的参数往往有巨大作用,但因为太缺乏通用性,关注的人不多。
    知人所不知,方可能人所不能。

    https://github.com/sekrit-twc/zimg/issues/164]
    zimg库解决架构不适配的--disable-simd

    提起WASM寻址,不得不提pkg-config,它确保了编译的正确运行,但外界主观却感知不到它的作用。我们编译一个大型C++库前,往往需要先用WASM编译很多小的依赖库,此时的小依赖库的编译目录必须是大型C++库的pkg-config寻址路径之一。
    道理很浅显,但落实很难,除非无脑把所有库的build目录都设置为/usr/local。所以更好的建议是,每次手动把编译后小依赖库的.pc文件复制到/usr/share/pkgconfg。

    https://people.freedesktop.org/~dbn/pkg-config-guide.html


    虽然进行了充分的事前准备,但编译往往仍会报错,就像行走江湖往往会踩坑,多修行功法方能化险为夷。

    WASM,有成熟的将C++库编译到前端使用的链路,原来的库能力越强,WASM编译后的收获越大。但是WASM所用emcc编译和传统的gcc编译互不兼容,编译出的文件互相都不认,使用一个就需要完全摒弃另一个。编译一个C++库时,除了系统自带的原装库外,所有它需要的第三方C++库,都需要清空之前gcc的编译结果,用emcc重新编译一遍。
    WASM整体心法最讲究“排他”,每当遇到具体细节的报错,或者某个具体编译功法走不通时,回头想想是不是中间的gcc结果文件没删干净,或者哪个依赖库还没用emcc编译过,往往能迎刃而解。
    https://jeromewu.github.io/build ... le-with-emscripten/
    如何指定emcc替代gcc作为编译器?

    configure文件中,往往会有对pkg-config依赖库版本的硬性检查,通不过检查则中止编译。由于依赖库版本号和库名称的变化,许多检查规则不再适用,此时出于严谨的检查就变成了拖后腿的负担。
    所以,有时候我们需要根据找不到某库类型的编译报错,检查pkg-config寻址的具体库是否存在。确认存在后,直接深入configure文件,操刀更改具体的检查规则。要是能提个issue顺便造福后人就更好了。

    https://github.com/FFmpeg/FFmpeg/blob/master/configure%23L6649
    FFmpeg对zimg依赖库的检测过时,编译时报错

    有时候会遇到真正的难题,我们费尽全力从WASM的角度也没能解决,这种时候就需要寻找外援了。
    尝试联系一下C++库的作者,提个issue,请他帮忙配合从C++库源码的角度出发解决对接WASM的问题。没有人会比作者更了解一个C++库的源码和函数调用链,大家都是江湖人士,向来义薄云天,相信他们一定会不吝赐教。

    https://github.com/sekrit-twc/zimg/issues/167
    与zimg库作者配合完成的一次WASM对接

    WASM编译时需要用到许多Linux系统库。这些系统库在最初创立的时候肯定想不到未来还有一个WASM这样的后起之秀来整合它们的生态,所以部分系统库的默认值是不适配WASM的。
    这一类问题相关的报错往往停留在表象,只提示编译出的某些文件识别不了。这时候就要抓筋拿穴,顺着编译出问题文件的函数调用链,逐个去筛查可能的问题语句,找在此过程中用到的系统库,逐个筛查、替换默认值,直到表象问题褪去暴露出深层问题,从而制定解决方案。

    https://github.com/ffmpegwasm/ff ... cripts/var.sh%23L50
    libvpx编译时需要手动指定STRIP库为”llvm-strip“,否则WASM识别不了编译出的.o文件

    https://picx.zhimg.com/80/v2-d05 ... ebp?source=1940ef5c[/img]

    WASM编译器Emscripten的版本更新越来越频繁,新旧版本API区别不少。有的名称直接换了,还有的直接过时淘汰了。但文档更新缓慢,很多API没有及时换掉,因此引发的编译报错会让人云里雾里,找不出原因。
    因此需要对Emscripten的常用功能建立完整的认知,各部分参数的常规取值有比较深的印象,接近于了如指掌的水平,在编译时遇到Emscripten本身的功能或参数报错,才能一次发力、一招制敌,很快地找到是哪部分API的问题。

    https://github.com/emscripten-co ... b/main/ChangeLog.md

    https://github.com/emscripten-core/emscripten/pull/12935
    从这次更改之后,从前的proxy_main API,就改为了emscripten_proxy_main
    \
         编译成功后,我们终于拥有了第一个WASM可用版本,下面就是测试与性能提升。

    对于WASM来说,快有两方面,加载快,运算快。
    加载快,需要砍掉包体积:

    https://github.com/FFmpeg/FFmpeg/blob/master/configure%23L114
    编译前通过禁用不必要功能优化包体积

    https://emscripten.org/docs/optimizing/Optimizing-Code.html
    编译时通过编译参数优化包体积

    https://developers.google.com/we ... 2587%25E6%259C%25AC
    编译完成后通过gzip减小传输包体积

    https://webassembly.github.io/binaryen/shrink.html
    将WASM包作为输入,进行二次体积优化
    运算快,需要优化所用算法、深度利用硬件性能:
    WASM包跑在浏览器里,有天生的限制,需要经过浏览器内核这一层的虚拟化调度,实际CPU并行核数和设定并行核数并不完全一致。选一个时间复杂度更低的算法、试验出一个本机最快的并行核数,是最好的办法。

    https://morioh.com/p/e7304dcee201
    测试WASM单文件体积上限

    https://iwiki.woa.com/pages/viewpage.action%3FpageId%3D1404361762
    测试WASM功能中支持的哪些文件格式

    测试WASM单次处理速度  
    https://iwiki.woa.com/pages/viewpage.action?pageId=807725558

    测试WASM同时的最大并行任务数
    https://stackoverflow.com/questi ... mits-in-webassembly

    现阶段WASM还没有公认的最优化编译实践,更多还是各凭本事,从混沌中摸索出一条路来,所以各方面都会有一定优化空间。
    限于整个WASM生态相关编译链路目前的开发进展,当触碰到目前WASM的能力边界时,每往外走一步,都需要无数扎根在底层编译的努力。时光有限,使用WASM高级特性遇到瓶颈时还是最好给团队和自己划定时间投入上限。
    https://www.wasm.com.cn/roadmap/

    WASM的路线图全部读完,功夫到此已练至大成,恭喜少侠!

      [   在WASM的江湖中,有太多的未竟之业和未解之谜,个人的努力实在是微不足道。但趁年轻,怕什么真理无穷,进一寸有一寸的欢喜。余心所善,九死不悔。

Archiver|手机版|小黑屋|ad208三国

GMT+8, 2024-4-28 02:55

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表