杭州供卵试管助孕网

WebAssembly入门
作者:admin来源:未知时间:2024-05-04
引言

先看下官网给的定义。

WebAssembly是基于栈式虚拟机的二进制指令集,可以作为编程语言的编译目标,能够部署在web客户端和服务端的应用中。

第一次看到这个定义的时候是一头雾水,翻了一些资料渐渐有了点轮廓,下边分享下我目前的理解。

首先WebAssembly是由Web和Assembly两个词构成,其中Web表明它一定和前端有关。Assembly的意思是汇编,汇编对应机器码,而机器码和CPU的指令集有关,接下来补一下相关的知识。

相关概念

其中指令集、操作系统相关的知识,之前总结过几篇文章,到底学哪一门编程语言、x86,x64,x86-64,amd64,arm指令集架构之间的关系、linux和Android的关系,可以先过去看一下,这里的话抽主要的部分回顾一下。

参考上图,计算机的主要架构如上。最底层是CPU的指令集,主要分为复杂指令集和简单指令集。

复杂指令集是x86、x64(也叫x86-64,amd64)两种架构,专利在Intel和AMD两家公司手里,该架构CPU主要是Intel和AMD两家公司,这种CPU常用在PC机上,包括Windows,macOS和Linux。

简单指令集是arm一种架构,专利在ARM公司手里,该架构CPU主要有高通、三星、苹果、华为海思、联发科等公司。这种CPU常用在手机上,包括安卓和苹果。

指令集是什么呢?直接把阮一峰的老师的一个例子粘过来,大家可以看一下。

c语言的源程序。

intadd_a_and_b(inta,intb){returna+b;}intmain(){returnadd_a_and_b(2,3);}

所对应的汇编就是下边的样子。

_add_a_and_b:push%ebxmov%eax,[%esp+8]mov%ebx,[%esp+12]add%eax,%ebxpop%ebxret_main:push3push2call_add_a_and_badd%esp,8ret

这里的push、mov每一条指令就是指令集规定的内容,规定了操作码、操作数以及具体的功能。当然这里是用汇编表示的,主要是为了我们人类来读写,最终还会转成0,1序列。上边每个单词都会有一个数字相对应,比如add指令对应00000011。

通过规定的指令集(加法的指令,压栈指令等),编写相关程序,然后CPU就会一条一条的执行,最终实现相应的功能。

而WebAssembly就规定了一套指令集,更准确的来说是虚拟指令集,因为这套指令集是跑在虚拟机上的,而不是直接由硬件运行。

历史

上边我们知道了WebAssembly的Assembly,即汇编,也就是指令集。下边在回顾下Web,即WebAssembly诞生的原因。

这里就得谈到javaScript了,众所周知,javaScript是一门动态类型的语言,编写程序时无需考虑变量类型,而且还可以运行时改变类型。对于我们开发者,确实很方便,但对于运行它的引擎就很有问题了。参考这里的一张图,看一下V8引擎从js源码到执行的一个过程。

由于js的动态类型,解释器在执行代码的时候会在类型判断上带来一定的性能消耗,降低执行速度。所以V8引擎采用了JIT(即时编译技术)技术,监控一些经常执行的代码,将其编译成CPU直接执行的机器码,提高执行速度。但由于js动态类型,在某些情况下还得反优化,回到字节码进行执行。

随着前端的不断发展,项目的大小和复杂度不断增大,对于某些场景,性能上可能已经无法满足,浏览器厂商们也一直在探索性能优化的方法。

NaCl/PNaCl

2011年Google在Chrome中使用了NaCl技术,可以使得C语言编写的程序运行到浏览器中,下边是维基百科的定义。

但一个完整的NaCl应用,在分发时需要提供支持多个架构平台(X86/X64/ARM等)的模块文件,后来谷歌又推出了与底层架构无关的PNaCl技术。但由于其开发难度、兼容性等问题最终没有普及开来。在2017年Google宣布放弃PNaCl转向WebAssembly。

是Mozilla在2013年推出的,是javaScript的一个严格子集,可以作为C/C++编译的目标语言,从而使得js引擎可以采用AOT(AheadOfTime)的编译策略,也就是在运行前直接编译成机器码,因此运行速度会有一定的提升。

通常不直接编写,而是作为一种通过编译器生成的中间语言,该编译器获取C++或其他语言的源代码,然后输出。

例如下边的C语言代码。

intf(inti){returni+1;}

经过编译器编译会生成下边的js代码。

functionf(i){i=i|0;return(i+1)|0;}

注意这里的|0在js中相当于和0进行了或操作,所以不影响原本的逻辑。在中起到了类型标记的作用,这样js引擎执行的时候就知道i是一个整型,返回值是一个整型。除了或操作这种,标准中还规定了很多类似的标记规则,用于告诉js引擎变量的类型,便于进行AOT优化。

这看起来和TypeScript很像,但其实不是一种东西。TypeScript是js的一个超集,浏览器并不能直接执行ts,还需要转换为js去执行。ts主要是帮助我们开发人员去看的,增加了代码的可读性,也可以让编辑器提前发现一些错误。而是用于引擎的编译优化。

WebAssembly

接下来看一下WebAssembly的历史。

WebAssembly于2019年12月5日成为万维网联盟(W3C)的推荐标准,与HTML,CSS和JavaScript一起成为Web的第四种语言。

可以看一下目前浏览器的支持程度,已经算比较高了。

初体验

内部结构

目前已经有了将C/C++、Rust、ts、"C"{EMSCRIPTEN_KEEPALIVEintfibonacci(intn){if(n2){return1;}returnfibonacci(n-1)+fibonacci(n-2);}}

函数的定义置在extern“C”{}结构中,是为了防止函数名编译后被改变。EMSCRIPTEN_KEEPALIVE是为了确保函数不会在编译器的编译过程中,被DCE(DeadCode」limination)过程处理掉。

然后需要安装Emscripten用来将C++程序编译为WebAssembly(wasm)的程序,安装后执行下边的命令。

=1-

-sWASM=1表明编译成Webassembly的程序,-O3表明编译的优化程度,–no-entry参数告诉编译器没有声明main函数,-o指定生成的文件名。

让我们看一下生成的字节码文件。

Offset:000102030405060708090A0B0C0D0E0F00000000:0061736``00000010:017F017F60000060017F000307060201.`..`..00000020:000301000405006010180.p..00000030:028002060F027F01419088C0020B7F00..A..@.00000040:4184080B07880109066D656D6F727902A..:00195F5F696E6469726563745F66756E..__indirect_fun00000060:6374696F6E5F7461626C650100096669ction_tablefi00000070:626F6E6163636900010B5F696E697469bonacci_initi00000080:616C697A650000105F5F6572726E6F5Falize__errno_00000090:6C6F636174696F6E000509737461636Blocationstack000000a0:5361766500020C737461636B52657374SavestackRest000000b0:6F726500030A737461636B416C6C6F63orestackAlloc000000c0:00040A5F5F646174615F656E64030109__data_000000d0:07010041010B01000A66060300010B3DA..f..=000000e0:01027F41012101200041024E047F4100A.!.:210103402000417F6A100120016A2101!..@..!.00000100:200041034A21022000417E6A21002002..!A~j!00000110:0D000B200141016A0541010B0B040023...k00000130:40020000B05004180080BApq".$A

让我们来解读下,最开始的前八个字节0x00x610x730x6d0x10x00x00x0表明当前是一个wasm的模块。然后会分很多Section,FunctionSection,CodeSection等等,都有特定的数字对应,还有就是文章开头讲的指令操作符所对应的一些数字。

看着上边的字节码仿佛回到了上古时期直接用机器码编程的时代,当年出现了汇编语言。这里也会有类似汇编的东西,那就是WAT(WebAssemblyTextFormat)。

需要安装WABT,然后执行wasm2wat命令。

../wabt/bin/

然后就生成了文件。

(module(type(;0;)(func(resulti32)))(type(;1;)(func(parami32)(resulti32)))(type(;2;)(func))(type(;3;)(func(parami32)))(func(;0;)(type2)nop)(func(;1;)(type1)(parami32)(resulti32)(locali32i32)_sif(resulti32);;label=@1;;label=@2__if0(;@2;))(func(;2;)(type0)(resulti32))(func(;3;)(type3)(parami32))(func(;4;)(type1)(parami32)(resulti32))(func(;5;)(type0)(resulti32))(table(;0;)22funcref)(memory(;0;)256256)(global(;0;)(muti32)())(global(;1;)i32())(export"memory"(memory0))(export"__indirect_function_table"(table0))(export"fibonacci"(func1))(export"_initialize"(func0))(export"__errno_location"(func5))(export"stackSave"(func2))(export"stackRestore"(func3))(export"stackAlloc"(func4))(export"__data_"(global1))(elem(;0;)()func0))

上边的格式属于「S-表达式」,Lisp语言就是采用的这种表达式,每条语句都是先执行最里边括号的表达式然后依次展开。

使用方法

上边主要介绍了.wasm具体长什么样子,下边看一下怎么用到浏览器中。

从.wasm源文件到实例化的对象主要有三个步骤,加载-编译-实例化-调用。

加载:读取.wasm字节码到本地中,一般是通过fetch从网络中取得。

编译:在Worker线程进行,编译成平台相关的代码。

实例化:将宿主环境的一些对象、方法导入到wasm模块中,比如导入操作dom的方法。

调用:通过上一步已经实例化的对象,来调用wasm模块中的方法。

主要有两种类型的API,一种是js提供的api,另一种是Web提供的api,Web提供的api支持流式编译实例化。

js的方法,

(bufferSource,importObject),可以完成编译和实例化。

bufferSource是含有效Wasm模块二进制字节码的ArrayBuffer或TypedArray对象。

importObject是要导入到Wasm模块中的对象。

方法在调用后返回一个Promise对象,resolve后返回一个对象,该对象包含编译好的module和已经实例化的instance,模块导出的方法可以通过instance对象进行调用。

web的方法,

(source,importObject)。

不同之处在于第一个参数,这里的source指的是尚未Resolve的Response对象(调用后会返回该对象),好处就是可以边读取.wasm字节流,边进行编译。

其他参数和返回值和js的api均一致。

jsAPI尝试

先简单的尝试一下,我们直接构造一个wasm模块的TypedArray对象,该模块包含了一个add方法,然后调用进行编译和实例化。

对应的C++代码。

实现PC端的开发……也就是下边的样子。

但如果有了wasm,我们只需要选择任意一门语言,然后编译成wasm,就可以分发到各个平台上了。

这也是Wasm官方宣传的ing定律,AnyapplicationthatcanbecompiledtoWebAssembly,willbecompiledtoWebAssemblyeventually.

总结

此时回顾一下,WebAssebmly的定义,应该会清晰很多了。

它不是一种语言,而是规定了一种虚拟指令集,可以作为各个语言的编译目标,然后通过wasm的虚拟机运行到浏览器还有其他各个平台中。

对于前端领域,当前Webassembly在某些场景下可以有效提高前端项目的性能,并且可以将C/C++领域的一些优秀的库通过编译直接运行到浏览器中。如果前端遇到了性能的问题,不妨可以考虑下WebAssmbly的方案。

参考链接

[极客时间WebAssembly入门课](),很系统,强烈推荐

[WebAssembly现状与实战]()

[WebAssembly:anotherJVM?]()

[WhyWebAssemblyisaBigDeal]()

[AwesomeWebAssemblyLanguages]()

[汇编语言入门教程]()

[WebAssembly在eBay的实践:速度提升50倍](*q7psQqWMaVU8igJeD)


参考资料

今日头条

最新文章
  • 供卵试管不像自己_供卵助
  • 杭州有代生公司吗,2023 年
  • 儿童过敏性紫瘢好治吗
Copyright © 2002-2030杭州展瑞智慧科技有限公司 浙ICP备2022030342号-1 杭州供卵试管助孕网网站地图sitemap.xml tag列表    杭州正规试管供卵医院_杭州供卵试管包成功【价格透明,100%包成功】杭州供卵试管助孕网