网站首页 > 技术教程 正文
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
WebAssembly那些事
无论使用的是 Chrome、Firefox、Edge 还是 Safari浏览器,代码都是由 JavaScript 引擎解释和执行的,即浏览器只运行 JavaScript。 不幸的是,JavaScript 并不总是开发者想要执行的每项任务的理想选择,这就有了 WebAssembly 的用武之地。下面是MDN上对WebAssembly的描述:
WebAssembly or "wasm" is a new portable, size- and load-time-efficient format suitable for compilation to the web.
Chrome>57、Edge>16、Safari>11、FireFox>52、Opera>44等浏览器都已经支持WebAssembly。WebAssembly 是一种可以在现代浏览器中运行的新型代码, 它的创建是为了能获得更好的性能优势。 它是一种更偏底层的二进制格式,体积小,因此加载和执行速度很快。 开发者也不用直接编写 WebAssembly,而是可以通过将其他高级语言编译成为WebAssembly。
WebAssembly(汇编)通常是指类似于机器代码的人类可读语言,机器代码是处理器所理解的,即一堆数字。
为了在处理器上运行,每种高级编程语言都会被翻译成机器代码。不同类型的处理器架构需要不同的机器代码和不同类型的汇编。
尽管名字叫 WebAssembly,但它并不完全是一种汇编语言,因为它并不适用于任何特定的机器。 它适用于浏览器,当开发者交付要在浏览器中执行的最终代码时,开发者并不知道代码将在哪种机器上运行,而WebAssembly可以做到开发者底层完全无感。
实际上,WebAssembly 是一种用于概念机器的语言, 当浏览器下载 WebAssembly 代码时,它可以快速将其转换为任何机器的程序集。比如:下图展示了 WebAssembly 的格式,它具有易于阅读的文本格式特性 (.wat),而右侧的二进制表示是实际交付给浏览器运行的内容 (.wasm)。
WebAssembly 能够让开发者将 C、C++ 或 Rust 代码之类的东西编译成所谓的 WebAssembly 模块,同时可以将其加载到 Web 应用程序中并从 JavaScript 中调用它。但是需要声明的是:WebAssembly不是 JavaScript 的直接替代品,它的设计理念是与JavaScript一起工作。
1.为什么说Web是终态
Web的优势在于它在任何地方都有效,避免下载和安装应用程序等繁琐流程,从而实现立即交付。 它比直接在计算机上下载和运行二进制文件更安全,因为浏览器建立了安全机制,可以防止其中运行的代码干扰系统。 同时,在 Web 上共享内容也非常容易 ,通过URL即可实现,开发者还可以将Web内容托管在任何地方。
Web是应用程序可在任何设备上访问、共享的唯一真正通用的平台,从而允许开发者维护一个单一的代码库,同时保持更新迅速。
2.为什么需要 WebAssembly
比如一些特定的场景:视频游戏、视频编辑、3D 渲染或音乐制作等, 这些应用程序需要进行大量计算并且需要很高的性能,这种性能很难通过JavaScript得到保障。
JavaScript 最初只是一种简单的脚本语言,旨在为充满轻量级超文本文档的网络带来一些交互性。 它被设计为易于学习和编写,但并不是为了速度而设计的。 多年来,浏览器对它们解释 JavaScript 的方式进行了优化,从而带来了重大的性能改进。
随着JavaScript变得越来越快,开发者可以在浏览器中执行的操作开始逐步扩展。 新的 API 带来了交互式图形、视频流、离线浏览等功能。 反过来,越来越多以前仅限于本机的丰富应用程序开始出现在网络上。 今天,用户可以轻松地从浏览器编辑文档和发送电子邮件,但在某些领域,JavaScript 的性能仍然是无法磨灭的硬伤。
比如:视频游戏的性能局限一直极具挑战性,因为它们不仅要协调音频和视频,而且通常还要协调物理和人工智能,而WebAssembly 可以解决这些问题。
3.WebAssembly优势
3.1 速度
下载执行速度
WebAssembly 专为速度而生,它的二进制文件比文本 JavaScript 文件小得多,从而下载速度飞快,特别是在低速网络场景。
WebAssembly的解码和执行速度也更快。 JavaScript 是一种动态类型语言,变量类型不必预先定义,也不需要预先编译。 这使得编写代码变得容易和快速,但这也意味着 JavaScript 引擎有更多的工作要做。 它必须在页面上执行时解析、编译和优化代码。
解析 JavaScript 涉及将纯文本转换为称为抽象语法树 (AST) 的数据结构,并将其转换为二进制格式。 WebAssembly 以二进制形式交付,解码速度更快。 它是静态类型的,因此与 JavaScript 不同,引擎不需要在编译期间推测将使用什么类型。
大多数优化发生在源代码编译期间,甚至在它进入浏览器之前。 内存是手动管理的,就像 C 和 C++ 等语言一样,因此也没有垃圾收集。 所有这些都提供了更好、更可靠的性能。据统计, WASM 二进制文件的执行时间仅比相同本机代码的执行时间慢 20%。
WebAssembly缓存机制
浏览器为WebAssembly提供了很好的优化缓存机制,最大限度的提升浏览器中WebAssembly的运行效率。比如下面使用流式API方法compileStreaming 或 instantiateStreaming 编译或实例化 WebAssembly 模块,优化WebAssembly 代码缓存。
(async () => {
const fetchPromise = fetch('fibonacci.wasm');
const { instance } = await WebAssembly.instantiateStreaming(fetchPromise);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
下面使用的是instantiateStreaming方法:
(async () => {
const response = await fetch('fibonacci.wasm');
const module = await WebAssembly.compileStreaming(response);
const instance = await WebAssembly.instantiate(module);
const result = instance.exports.fibonacci(42);
console.log(result);
})();
注意:由于代码缓存取决于资源 URL 以及 .wasm 资源是否最新,开发人员应尽量保持两者稳定。 如果 .wasm 资源是从不同的 URL 获取,它被认为是不同,浏览器必须重新编译模块。 同样,如果 .wasm 资源在缓存中不再有效,则 Chrome 必须丢弃所有缓存的代码。
3.2 可移植性
要在设备上运行应用程序,它必须与设备的处理器架构和操作系统兼容。 这意味着需要为想要支持的每种操作系统和 CPU 架构组合编译源代码。 使用 WebAssembly 只需一个编译步骤,应用程序就可以在每一种现代浏览器中运行。
开发者不仅可以将自己的应用程序移植到 Web,还可以将现有的大量 C++ 库和开源应用程序移植到 Web。 它是一种几乎所有平台都支持的语言,包括 iOS 和 Android。 WebAssembly可以用作跨 Web 和移动部署的通用语言。
3.3 灵活性
到目前为止,JavaScript 一直是 Web 浏览器中唯一完全受支持的语言。 有了 WebAssembly,Web 开发人员将能够选择其他语言,更多的开发人员将能够为 Web 编写代码。 JavaScript 仍然是大多数用例的最佳选择,但当确实需要性能提升时,可以选择使用更加优秀的语言。 UI 和应用程序逻辑等部分用 JavaScript 编写,核心功能在 WebAssembly 中。
根据MDN数据文档数据,目前完全支持的语言是 C、C++ 和 Rust,但还有许多其他语言正在开发中,包括 Kotlin 和 .NET,这两种语言都已经提供了实验性支持。
4.使用WebAssembly
4.1 准备工作
如果您已经使用 Emscripten 等工具编译了另一种语言的模块,或者自己加载并运行代码,那么下一步是了解如何使用 WebAssembly JavaScript API 的其他功能。
Emscripten 是一个开源的编译器,可以将 C/C++ 代码编译为 WebAssembly 编程语言的代码。Emscripten 的底层是基于 LLVM 编译器的,可以查看其开源的 emscripten llvm 和 emscripten clang 。
让我们通过一步一步的例子来了解如何在 WebAssembly 中使用 Javascript API和如何在网页中加载一个 wasm 模块。
- 首先需要一个 wasm 模块,下载 simple.wasm 文件到本机的一个新的目录下。
- 确保本机使用的是支持 webassembly 的浏览器,Firefox 52+ 和 Chrome 57+ 是默认支持 webassembly 的。
- 然后,创建一个简单的 HTML 文件命名为 index.html 和并且你的本机的 wasm 文件处于同一目录下 ( 如果你没有模板可以使用我们提供的 simple template )
- 为了帮助理解发生了什么,让我们来看看这个 wasm 模块的文本表示 (也可以在将 WebAssembly 文本格式转换为 wasm见到):
(module
(func $i (import "imports" "imported_func") (param i32))
(func (export "exported_func")
i32.const 42
call $i))
在第二行,你将看到导入有一个两级命名空间 —— 内部函数 $i 是从 imports.imported_func 导入的。编写要导入到 wasm 模块的对象时,需要在 JavaScript 中反映这个两级命名空间。创建一个 <script></script> 节点在你的 HTML 文件中,并且添加下面的代码:
var importObject = {
imports: {
imported_func: function(arg) {
console.log(arg);
}
}
};
如上所述,在 imports.imported_func 中有我们导入的函数。
4.2 加载并使用 wasm 模块
当导入了对象后,将获取 wasm 文件,使其在 array buffer 可用,然后就可以使用其导出的函数。下面添加以下代码到你的脚本中:
fetch('simple.wasm')
.then(res =>
res.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results => {
results.instance.exports.exported_func();
});
这样做的结果是执行导出的 WebAssembly 函数 exported_func,又调用了另一个导入的 JavaScript 函数 imported_func, 它将 WebAssembly 实例中提供的值打印到控制台。
5.本文总结
本文主要和大家介绍WebAssembly,即浏览器支持的除JavaScript外的新的语言,文章聚焦在什么是WebAssembly、为什么说Web是终态 、为什么需要 WebAssembly 、WebAssembly优势 、如何使用WebAssembly等维度。因为篇幅有限,文章并没有过多展开,如果有兴趣,文末的参考资料提供了优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!
参考资料
https://developer.chrome.com/blog/wasm-debugging-2020/
https://developer.mozilla.org/zh-CN/docs/WebAssembly/Using_the_JavaScript_API
https://caniuse.com/?search=WebAssembly
https://www.codercto.com/a/59841.html
英文链接:https://blog.logrocket.com/webassembly-how-and-why-559b7f96cd71/
英文作者:Milica Mihajlija
翻译作者:高级前端进阶,有改动
- 上一篇: 「留学记」穿厌了HM和ZARA?这些牌子可都美翻了
- 下一篇: 住太空酒店,现在攒钱来得及吗
猜你喜欢
- 2025-01-03 5分钟实现一个简单的 WebAssembly 应用|WebAssembly 入门教程
- 2025-01-03 W3C 发布 WebAssembly 2.0 工作草案
- 2025-01-03 WebAssembly入门(golang版)
- 2025-01-03 如何看待 WebAssembly 这门技术?
- 2025-01-03 开发者通过WebAssembly力求让LibreOffice在Web浏览器中运行
- 2025-01-03 使用 WebAssembly 和 Go 编写前端 Web 框架
- 2025-01-03 《永劫无间》出现部分按键失效问题,官方给出注册表解决方案
- 2025-01-03 「技术分享」WebAssembly能否重新定义前端开发模式?
- 2025-01-03 乙肝在研新药0731,2期a部分启动,预计2023年8月完成
- 2025-01-03 如何在 Deno 应用程序中调用 Rust 函数?
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)