为什么要这么做?编译js比解释js更快是必然的
wasm是什么?
我期望是一个二进制文件
WebAssembly(又名wasm)是一种高效的,低级别的编程语言。 它让我们能够使用JavaScript以外的语言(例如C,C ++,Rust或其他)编写程序,然后将其编译成WebAssembly,进而生成一个加载和执行速度非常快的Web应用程序。
WebAssembly被设计为针对Size和Load Time进行优化的格式,可以在各个硬件平台上以native speed运行;
安全性:WebAssembly是运行在沙盒内的,甚至可以和当前的Java虚拟机共享一套环境,并且也遵守浏览器各种跨域不跨域的规章制度;
开放性:WebAssembly开放标准,不受任何一家厂商控制,并且被设计为可以和Java API和Context交互
短期上 WASM 显然无法替代 JS——工具链调试困难、包体积庞大冗余、调 OpenGL 都要走回 JS 到 WebGL,性能未必有保证等。我们的团队踩过移植 C++ 原生渲染引擎的坑,这东西不深度掌握的话,目前只适合保证一个原生 App 在 Web 上原汁原味地凑合能用。要想做到好用,或是封装成完整的引擎级 API 在上层用 JS 深度开发,保证让人难受。我也不知道 WASM 为什么能这么巧妙地卡在原生团队和 Web 团队各自的边界之外,在完整从下到上搞 UI 的正经前端项目上(而不是音视频等特殊场景)让两边用起来都这么费劲。
V8 几乎是这个星球上最先进的工业级脚本语言引擎。别管你代码怎么梭,只要你能让 V8 走在 Happy Path 上,那妥妥都是原生级性能。
ES 规范在不断演化。这门语言向下兼容性极佳并且仍然在进化。技术圈内独家的转译玩法,让隔壁还有人为 2 还是 3 站队的时候,前端们都在用 Chrome 明年才会支持的语法特性了。
NPM 背后那个巨大的娱乐圈,哦不,社区支持。
V8 的技术路线很可能已经到达瓶颈了——不少数据显示,这条路线的综合性能上限,大约相当于纯原生应用的 1/20,而 WASM 能优化到原生的 1/4 左右。问题在于,大多数前端应用是事件驱动的,JS 完全不会 60fps 执行,甚至初级开发者还常常随手 setTimeout 几十毫秒而不影响体验。对一个 3Ghz 的 CPU 来说,在 50ms 内它就能执行 1.5 亿条指令。这个数字除以 JS 损耗的 20 倍,那也是 750 万条指令啊。
也就是说,gcc或者别的能直接编译出wasm
js解释器是v8,js编译器是
V8 执行一段 JavaScript 代码流程
生成抽象语法树(AST)和执行上下文
无论你使用的是解释型语言还是编译型语言,在编译过程中,它们都会生成一个 AST。这和渲染引擎将 HTML 格式文件转换为计算机可以理解的 DOM 树的情况类似。
第一阶段是分词(tokenize),又称为词法分析,其作用是将一行行的源码拆解成一个个 token。
第二阶段是解析(parse),又称为语法分析,其作用是将上一步生成的 token 数据,根据语法规则转为 AST。
将代码翻译成字节码(Bytecode)
由于直接执行机器码效率高,但是运行在 512M 内存的手机上,内存占用问题也暴露出来了,因为 V8 需要消耗大量的内存来存放转换后的机器码。为了解决内存占用问题,V8 团队大幅重构了引擎架构,引入字节码,并且抛弃了之前的编译器,
字节码就是介于 AST 和机器码之间的一种代码。但是与特定类型的机器码无关,字节码需要通过解释器将其转换为机器码后才能执行。
机器码所占用的空间远远超过了字节码,所以使用字节码可以减少系统的内存使用。
执行代码即时编译器(JIT)
在 Ignition 执行字节码的过程中,如果发现有热点代码(HotSpot),比如一段代码被重复执行多次,这种就称为热点代码,那么后台的编译器 TurboFan就会把该段热点的字节码编译为高效的机器码,然后当再次执行这段被优化的代码时,只需要执行编译后的机器码就可以了,这样就大大提升了代码的执行效率。
Java 和 Python 的虚拟机也都是基于即时编译(JIT)(字节码配合解释器和编译器)实现的。具体到 V8,就是指解释器 Ignition 在解释执行字节码的同时,收集代码信息,当它发现某一部分代码变热了之后,TurboFan 编译器就把热点的字节码转换为机器码,并把转换后的机器码保存起来,以备下次使用。
js没有编译器,因为js是嵌在html的,脱离html并没有其他应用场景