| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> JavaScript知识库 -> 认识 WebAssembly -> 正文阅读 |
|
[JavaScript知识库]认识 WebAssembly |
起源WebAssembly 起源于 Mozilla 员工的一个业余项目。2010年,在 Mozilla 从事 Android Firefox 开发的 Alon Zakai,为了把他以前开发的游戏引擎移植到浏览器上运行,利用业余时间开发了一款名叫 Emscripten 的编译器,可以把 C++ 代码通过 LLVM IR 编译成 JavaScript 代码。 到了 2011 年底,Emscripten 甚至能够成功编译 Python 和 Doom 等大型 C++ 项目,Mozilla 此时觉得这个项目很有前途,于是成立团队并邀请 Alon 全职开发这个项目。2013 年 Alon 和其他成员一起提出了 asm.js 规范,asm.js 是 JavaScript 语言的一个严格子集,试图通过“减少动态特性”和”添加类型提示“的方式帮助浏览器提升 JavaScript 优化空间。相较于完整的 JavaScript 语言,裁剪后的 asm.js 更靠近底层,更适合作为编译器目标语言。 asm.js 只提供两种数据类型:32位带符号整数,64位带符号浮点数,其他数据类型比如字符串、布尔值或者对象,asm.js 一概不提供,它们都是以数值的形式存在,保存在内存中,通过 TypedArray 调用。类型的声明也有固定写法:
支持 asm.js 的引擎提前识别出了类型,可以进行激进的 JIT(即时编译)优化,甚至是 AOT(事先编译)编译,大幅提升性能。不支持 asm.js 按普通 JavaScript 代码执行也不会影响运行结果。 但是 asm.js 的缺点也很明显,那就是“底层”得不够彻底,例如代码仍然是文本格式;代码编写仍然受 JavaScript 语法限制;浏览器仍然需要完成解析脚本、解释执行、收集性能指标、JIT 编译等一系列步骤。如果采用像 Java 类文件那样的二进制格式,不仅能缩小文件体积,减少网络传输时间和解析时间,还能选用更接近机器的字节码,这样 AOT/JIT 编译器实现起来会更轻松,效果也更好。 与此同时,Google 的 Chrome 团队也在试图解决 JavaScript 性能问题,但方向有所不同。Chrome 给出的解决方案是 NaCl(Google Native Client)和 PNaCl(Portable NaCl)。通过 NaCl/PNaC1,Chrome 浏览器可以在沙箱环境中直接执行本地代码。 asm.js 和 NaCl/PNaC1 技术各有优缺点,二者可以取长补短。Mozilla 和 Google也看到了这一点,所以从 2013 年开始,两个团队就经常交流和合作。后来他们决定结合两个项目的长处,合作开发一种基于字节码的技术。到了 2015 年,“WebAssembly” 确定为正式名称并对外公开,W3C 成立了 WASM 社区小组(成员包括Chrome、Edge、Firefox 和 WebKit),致力于推动 WASM 技术的发展。 2016 年 Rust 1.14发布,开始支持 WASM。 简介官方给出的定义:WebAssembly / WASM 是基于栈式虚拟机的二进制指令集,可以作为编程语言的编译目标,能够部署在 Web 客户端和服务端的应用中。 WebAssembly 具有如下特性:
也就是说 WebAssembly 可以使得以各种语言编写的代码都可以以接近原生的速度在浏览器中运行。 WebAssembly 也被设计为与 JavaScript 共存并协同工作,相对于 JavaScript(包括 asm.js)解决了如下几个问题:
不过 WebAssembly 并不是纯浏览器平台的技术,犹如 JavaScript 与 Node.js,如今它也有自己的 Runtime,在浏览器之外的云原生、区块链、安全等系统应用领域都有诸多应用。 编译C / C++ 通过 Emscripten 编译:
Rust 通过 Cargo 编译:
还可以进一步压缩体积:
Golang 内置编译:
运行在 JavaScript 运行为了在 JavaScript 中运行 WebAssembly,在编译/实例化之前,你首先需要把模块放入内存,比如通过 XMLHttpRequest 或 Fetch,模块将会被初始化为带类型数组。 使用 Fetch 的例子:
上述方式是先创建一个包含你的 WebAssembly 模块二进制代码的 ArrayBuffer,然后使用 你也可以使用
WebAssembly 计划未来会支持 在浏览器之外运行Wasm 社区提供了很多 Runtime 容器,让 WASM 可以在浏览器之外的系统上执行,并且运行环境是沙箱化的。 目前比较流行的 Runtime:
底层概念模块WebAssembly 程序的主要单元称为模块(Module),这个术语既用来表示代码的二进制版本,也表示浏览器中的编译后版本。 一个大型 WebAssembly 应用往往由多个子模块组成,每个模块都拥有自己的独立数据资源,因此子模块无法篡改其他模块的数据;另外每个模块所能使用的权限由最上层的调用者指定,因此第三方子模块无法在上层模块不感知的情况下越权调用,这种权限管理类似于 Android 开发需要预先声明所有依赖的权限一样。 当其他高级语言编译成 WebAssembly 后,会成为了一个模块二进制文件,文件名是以
前4 字节被称为“魔数(Magic Number)”,对应 段在模块头之后就是模块的主体内容,这些内容被分门别类放在不同的段(Section),Wasm 把特定功能或者有相关联的代码放进一个特定的段中,有些段是任何的模块都必需的,有些段是可选的。 段可能会包含多个项目,Wasm 规范一共定义了 12 种段,并给每种段分配了 ID。除了自定义段以外,其他所有的段都最多只能出现一次,且必须按照段 ID 递增的顺序出现。 下面是各个段的说明,其中粗体是必需存在的段:
数据类型WASM 在二进制编码里的数据类型如下:
对于语言本身,提供以下数值类型:
每个参数和局部变量都必须是以上四种值类型之一 ,函数签名由 0 或多个参数的类型序列及 0 或多个返回值的类型序列组成。(在最小可行版本中,一个函数最多可以有一个返回类型)。需要注意的是,值类型 i32 和 i64 不是固有有符号或无符号的。 这些类型的解释取决于某个具体的运算符。 布尔值用无符号 32 位整数表示,0 为 false,非 0 值为 true。所有其他值类型(如字符串)需要在模块的线性内存空间中表示。 WATWASM 二进制文件是不可读的,WAT (WebAssembly Text Format) 是另外一种输出格式,是使用 “S- 表达式” 的文本格式,可以近似理解为与二进制等价的汇编语言。 部分浏览器的开发者工具支持将 WASM 转换成 WAT 查看,便于在线调试。社区提供了 WASIWebAssembly 虽然是为了 Web 而生,但并不意味着它只能也不打算只在浏览器上运行。开发人员想将它推向了浏览器之外,而这需要提供一套与操作系统交互的接口。 由于 WebAssembly 是基于概念机器的汇编语言,而不是物理机器,因此,WebAssembly提供了一种快速,可扩展,安全的方式来在所有计算机上运行相同的代码。同时为了在所有不同的操作系统上运行,WebAssembly 需要一个概念机器的系统接口,而不是任何单个操作系统。于是开发人员定义了一种与不同操作系统通信统一标准,名为 WASI (WebAssembly System Interface),它是为 WASM 专门设计一套引擎无关(engine-indepent)、面向非 Web 系统(non-Web system-oriented)的 API 标准。 WASI 的设计遵循两大原则:
基于上述两项关键原则,WASI 被设计为一组模块化的标准接口,其中最基础的核心模块为
WASI 在 WASM 字节码与虚拟机之间,增加了一层“系统调用抽象层”。比如对于在 C/C++ 源码中使用的 WASI 主要工作是定义 Import 接口标准,提供通用 Import 接口在不同系统上的具体实现(与不同操作系统上实现libc模式类似)。 基于 WASI 的设计思路,针对不同的领域我们还可以提供更上层的WADSI(WebAssembly Domain Specific Interface),将领域通用的接口作为 Import 接口提供,从而使得开发者可以直接使用。 安全性WebAssembly 的安全性来源之一是,它是第一个共享 JavaScript VM 的语言,而 JavaScript VM 在运行时是沙箱化的,同时也经历了多年的检验和安全测试,这确保了其安全性。WebAssembly 模块的可访问范围不超过 JavaScript 的访问范围,同时也会遵守相同的安全性规则,包括同源策略(same-origin policy)这样的增强规则。 与桌面应用程序不同,WebAssembly 模块对设备内存没有直接访问权限,而是运行时环境在初始化过程中向模块传递一个 ArrayBuffer 。模块将这个 ArrayBuffer 当作线性内存来使用,WebAssembly 框架执行检查以确保代码不会对这个数组进行越界操作。 对于像函数指针这样存储在 Table 段中的项目,WebAssembly 模块也不能直接访问。代码会用索引值向WebAssembly框架提出访问某个项目的请求。然后框架访问内存,并代表代码执行这个项目。 在 C++ 中,执行栈与线性内存一起位于内存中,虽然 C++ 代码不应该修改执行栈,但是它可以使用指针实现修改。WebAssembly的执行栈与线性内存是分离的,代码无法访问。 应用案例谷歌地球 AutoCAD Figma 结语可以看出 WebAssembly 并不是用来完全取代 JavaScript,而是作为 Web 技术的补充,在性能和代码复用等方面弥补 JavaScript 的局限。正如 WASM 官方的口号:“所有可以用 WebAssembly 实现的终将会用 WebAssembly 实现”,WebAssembly 的最终目标是用任何语言编译而来并可以高效运行在任何平台。最重要的是它背靠 Google、Mozilla、Edge 等主流开发机构的支持,相信在未来一定还会有更长足的发展。 参考资料 |
|
JavaScript知识库 最新文章 |
ES6的相关知识点 |
react 函数式组件 & react其他一些总结 |
Vue基础超详细 |
前端JS也可以连点成线(Vue中运用 AntVG6) |
Vue事件处理的基本使用 |
Vue后台项目的记录 (一) |
前后端分离vue跨域,devServer配置proxy代理 |
TypeScript |
初识vuex |
vue项目安装包指令收集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 9:20:20- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |