WebAssembly—学习笔记

WebAssembly是一种能在浏览器上运行非JavaScript编程语言的技术。它通过减少解析、编译和优化时间,提高执行速度,尤其是在循环体中代码运行更快。与JavaScript相比,WebAssembly在拉取、解析、编译、执行和内存管理方面都有显著优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念

WebAssembly是一种使用非JavaScript编程语言编写代码并且能在浏览器上运行的技术方案。

1995年JavaScript诞生,2008年浏览器加入即时编译器JIT,当JavaScript在运行的时候,JIT可以看到模式,并根据这些模式使代码运行更快,JavaScript的运行速度快了10倍。
在这里插入图片描述
现在WebAssembly是另一个转折点。
在这里插入图片描述

JavaScript如何在浏览器中运行

JavaScript引擎的工作就是把人类语义转化成机器所理解的语言。

代码转翻译机器语言

通常有两种翻译方法将代码翻译成机器语言,可以使用解释器或者编译器。

  • 解释器,翻译的过程基本上是一行一行即时生效的。
    在这里插入图片描述

    • 解释器可以快速启动和运行,不需要完成整个编译步骤,这是浏览器最初使用JavaScript解释器的原因。

    • 但是使用解释器的弊端是当运行相同代码的时候,例如在循环体中,需要一遍一遍的做同样的翻译。

    • 在运行期间,没有时间来做优化。

  • 编译器,在执行前翻译。
    在这里插入图片描述

    • 编译器启动需要更多的时间,因为它必须在开始时完成编译步骤。
    • 在循环体中的代码运行的更快,因为它不需要为每次循环重复转换。
    • 编译器有更多的时间查看代码并对其进行编辑,以便它运行的更快,这些编译称为优化。

JIT

为了解决解释器在循环体中做重复翻译的问题,浏览器开始混合编程。为JavaScript引擎添加了监视器(也称为分析器)。该监视器在运行时监视代码,并记录它运行的次数以及使用的数据类型。

如果相同的代码运行了几次,则该段代码标记为“warm”,并且JIT会将其交给基础编译器处理。
在这里插入图片描述
如果运行次数比较多,那么标记为“hot”,同时JIT会将其交给优化编译器处理。
在这里插入图片描述

WebAssembly

WebAssembly是一种在网页上运行JavaScript之外的编程语言的方法。但是这并不意味这要么使用WebAssembly,要么使用JavaScript。可以在同一应用程序中使用WebAssembly和JavaScript,JavaScript可以调用WebAssembly模块定义的函数。
Assembly可以将高级语言翻译成机器语言。
在这里插入图片描述
WebAssembly是一个概念机上的机器语言,不是一个真正存在的物理机上运行的机器语言。WebAssembly指令有时候被称为虚拟指令。它比JavaScript代码更快更直接的转换成机器代码,但它们不直接和特定硬件的特定机器代码对应。
在这里插入图片描述

  • 编译成.wasm
    在这里插入图片描述
  • JavaScript调用.wasm
function fetchAndInstantiate(url, importObject) {
  return fetch(url).then(response =>
    response.arrayBuffer()
  ).then(bytes =>
    WebAssembly.instantiate(bytes, importObject)
  ).then(results =>
    results.instance
  );
}

WebAssembly加速原理

使用WebAssembly或JavaScript进行编程不是一种选择。 也不希望太多开发人员编写完整的WebAssembly代码库。希望开发人员用WebAssembly替换部分JavaScript代码,以提高速度。

JS引擎执行任何一项任务的时间取决于页面使用的JavaScript。 此图表并不代表精确的性能数字。 相反,它旨在提供一个高级模型,说明JS与WebAssembly中相同功能的性能如何不同。

在这里插入图片描述
每个条形显示执行特定任务所花费的时间。

  • 解析 - 将源代码处理为解释器可以运行的内容所花费的时间。
  • 编译+优化 - 在基础编译器和优化编译器中花费的时间。一些优化编译器的工作不在主线程上,所以它不包含在这里。
  • 重新优化 - JIT在其假设失败时重新调整的时间,重新优化代码并将优化代码送回基础编译器。
  • 执行 - 运行代码所需的时间。
  • 垃圾收集 - 清理内存所花费的时间。

注意:这些任务不会以离散的块或特定的顺序发生。相反,它们将是交错的。解析、执行、编译、解析、执行交错执行。

WebAssembly典型的web应用

在这里插入图片描述

拉取

拉取耗时主要是从服务器获取文件。因为WebAssembly比JavaScript更紧凑,所以获取它更快。 尽管压缩算法可以显着减小JavaScript包的大小,但WebAssembly的压缩二进制表示仍然较小。
这意味着在服务器和客户端之间传输它需要的时间更少。 在慢速网络上更明显。

解析

一旦到达浏览器,JavaScript源就会被解析为抽象语法树。
浏览器通常会懒惰地执行此操作,首先只解析它们真正需要的内容,而只是为尚未调用的函数创建存根。
从那里,AST被转换为特定于该JS引擎的中间表示(称为字节码)。
相比之下,WebAssembly不需要经历这种转换,因为它已经是一个中间表示。 它只需要解码和验证,以确保它没有任何错误。

编译+优化

JavaScript是在代码执行期间编译的。 根据运行时使用的类型,可能需要编译相同代码的多个版本。
WebAssembly更接近机器代码。

  • 在开始编译优化代码之前,编译器不必花时间运行代码来观察正在使用的类型。
  • 编译器不必根据它观察到的不同类型编译相同代码的不同版本。
  • 在LLVM中已经提前完成了更多优化。 因此,编译和优化它所需的工作量减少了。

重新优化

当JIT基于运行代码做出的假设结果不正确时,JIT必须抛弃优化版本的代码并重试它。

去优化有两个成本。 首先,需要一些时间来摆脱优化的代码并返回基础版本。 其次,如果该函数仍被大量调用,JIT可能会决定再次通过优化编译器发送它,因此需要再次编译它的成本。

在WebAssembly中,类似的东西是显式的,因此JIT不需要根据它在运行时收集的数据来对类型进行假设。 这意味着它不必经历重新优化循环。

执行

在WebAssembly中执行代码通常更快。WebAssembly不需要JIT对JavaScript进行的许多优化(例如类型特化)。

此外,WebAssembly专为编译器生成而设计,而不是供程序员编写。

由于程序员不需要直接编程,因此WebAssembly可以提供一组更适合机器的指令。根据您的代码所做的工作类型,这些指令的运行速度可以提高10%到800%。

垃圾回收

在JavaScript中,开发人员不必担心在不再需要时从内存中清除旧变量。 JS引擎会自动处理,但是无法控制垃圾收集器何时完成其工作,因此可能会在不方便的时候进行控制。 大多数浏览器都非常擅长调度它,但它仍然可能会妨碍代码的执行。

至少目前,WebAssembly根本不支持垃圾收集。 内存是手动管理的(就像C和C ++这样的语言)。 虽然这会使开发人员编程变得更加困难,但它也会使性能更加一致。

参考资料

  1. 几张图让你看懂WebAssembly
  2. A cartoon intro to WebAssembly
  3. A crash course in just-in-time(JIT) compilers
  4. A crash course in assembly
  5. Creating and working with WebAssembly modules
  6. What makes WebAssembly fast?
  7. Where is WebAssembly now and what’s next?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值