【翻译】WTF是WebAssembly?

当每个人都直接在 "裸机 "上部署代码时,我们的需求超过了我们所拥有的基础设施的能力,所以我们的基础设施演变成了虚拟机。 虚拟机的使用使我们能够在一块硬件上运行许多机器,这就产生了数据中心。

当我们超过了数据中心的能力来处理我们部署无数的虚拟机时,我们进入了docker镜像的时代,现在我们把docker镜像部署在虚拟机之上,而虚拟机又部署在裸机之上。

WebAssembly是部署单位的下一个演变。我们已经从定制安装的硬盘到裸机上的巧妙捆绑,再到虚拟机和docker镜像,现在我们有一个更小、更快、更便携、更安全的部署单位--WebAssembly模块

我们认为你应该关注WebAssembly,因为我们认为它完全有可能成为我们所知的计算的未来。

那么,WebAssembly是什么呢?

WebAssembly既不是网络也不是汇编

如果你在网上对WebAssembly做了任何研究,那么你肯定会遇到这个流行的小说法。它告诉我们很多关于WebAssembly不是什么,但它并没有给我们任何关于它什么的想法。希望这篇文章能消除一些困惑。

首先,让我们从WebAssembly一个基于堆栈的虚拟机这个概念开始。每台机器(虚拟的或其他的)都有一套核心的原始指令,可以用来告诉它要做什么。无论你使用什么高级编程语言,最终你的编译器的输出将是一个包含机器级代码的文件。

WebAssembly是一个虚拟机。它有自己的指令集,但负责执行这些指令的机器是虚拟的,它只是你电脑上的另一个进程。这对WebAssembly的重要性有深刻的影响,而且常常被低估。

WebAssembly使用的指令集是可移植的。这意味着,用WebAssembly字节码表达的东西不可能在一台机器上工作,而在另一台机器上则不可能。像WebAssembly这样基于堆栈的虚拟机速度很快,因为管理堆栈和在这些堆栈上执行操作的代码实际上非常简单,而且可以高度优化。WebAssembly的二进制文件(.wasm文件,我在这篇文章中可能会把WebAssembly简单地称为 "wasm")也很小。根据你正在构建的内容,功能齐全的wasm文件是以千字节为单位的,而不是以兆字节或千兆字节为单位。

原始的

WebAssembly是原始的,但有一个好的方式。我一直是一个做得比较少的语言的粉丝:语言的设计者花了时间和精力来减少语言中不应该出现的东西。WebAssembly之所以如此强大,正如我在这篇文章中所讨论的,主要是它不能做什么。

开发人员经常注意到(也害怕)wasm的第一件事是,唯一的数据类型是数字。函数只能接受和返回整数或浮点数的值,其中只有32位和64位的值是允许的。

这意味着像字符串、哈希图、数组、树、图元--所有我们日常认为理所当然的好东西,都不是WebAssembly核心规范的一部分。而是由高级语言在编译时将它们翻译成WebAssembly字节码。

让我们看看WebAssembly的核心是什么样子的。让我们假设我们的.wasm二进制文件的一部分包含以下字节。

0x41 0x09 0x41 0xA0 0x6A

这不一定是准确的(二进制格式有一些相当多的编码要求,在这一点上只会让我们感到困惑),但这将足以作为一个例子。让我们把它分解一下。

  • 0x41-i32常数
  • 0x09--数值9
  • 0x41- i32常数
  • 0xA0- 数值160
  • 0x6A-i32添加

第一条指令是一条i32.const指令(记住WebAssembly只支持i32、f32、i64和f64数字)。下一条指令是i32.const指令(记住WebAssembly只支持i32.f32.i64和f64的数字),它在堆栈中放置了一个常量值9。第三条指令是i32.add,它从堆栈中弹出两个值,将它们相加,然后将总和放回堆栈。因此,当虚拟机处理完这些字节码和参数后,它将把值169放在堆栈上。

携带

我已经提到,WebAssembly规范中的指令没有一条是针对操作系统或CPU架构的。这意味着,假设主机运行时(如网络浏览器或自定义嵌入器)符合规范,同样的WebAssembly文件可以在任何地方被解释,无论操作系统或CPU架构如何。

这具有巨大的意义,因为它意味着任何你可以用WebAssembly字节码表达的东西都可以被编译一次,并部署到多个目标,而无需修改。我们中的大多数人都听说过Java字节码的支持者所提出的 "一次编写,到处部署"的口号,但WASM并不只是另一个JVM或.NET CLR。首先,Java字节码并不具备真正的可移植性,不同的JVM可以以完全不同的方式执行,从而破坏可移植性。微软的.NET框架对可移植性提出了类似的要求,但JVM和.NET CLR都存在着(在我看来)太多的指令,无法进行移植,其中许多指令违反了可移植性的考虑。例如,JVM和.NET框架都允许访问操作系统,这立即使可移植性(和安全性,我将讨论)成为一个问题。

快速

主机运行时的工作很简单--读取操作码,管理堆栈和线性内存,并执行操作码指示的任何任务。正是这种简单性使得WebAssembly文件的处理速度快得令人难以置信。虽然有即时编译器(JIT)可以将wasm模块编译成本地代码,但许多运行时(如你的浏览器)仅依靠解释就可以达到惊人的速度。

可流式

另一种提高WebAssembly性能的方法是,wasm是可流式的。指令集的性质和.wasm文件内的代码组织是这样的,它可以被流化。

解释器可以WebAssembly文件中的第一条指令完成下载之前开始执行。虚拟机解释器不需要担心跳转指令指向尚未下载的位置,或试图访问尚未发现的资源。WebAssembly文件的组织有一种微妙的美感,它允许这种流媒体,所有支持WebAssembly的主要浏览器都支持流媒体执行。

小巧

Wasm是很小的。即使是通常产生最大的WebAssembly二进制文件的语言(Rust),产生的文件仍然比docker图像,甚至独立的,由Go等语言产生的操作系统和CPU特定的二进制文件小几个数量级,甚至Rust。正如我在下一篇关于WebAssembly的博文中所讨论的,有许多框架和自定义嵌入器利用WebAssembly的速度和(缺乏)大小来支持数百或数千个小模块在单个主机内运行。这种计算密度根本不可能用现在的语言和框架来实现 "传统 "的编译目标。

安全

WebAssembly是安全的。它默认是安全的,这是由于语言和规范的能力。首先,WebAssembly模块是被动的。它不能做任何事情,除非主机运行时间要求它。其次,wasm模块不能访问主机运行时的内存;它们利用自己的私有线性内存空间,最终归结为一个大的长的字节矢量。

WebAssembly没有内置的指令来访问文件系统,写到套接字,操作主机内存,访问网络服务,或以任何方式与操作系统互动。虽然像WASI这样的标准允许有限的操作系统访问,但这种访问也是使用能力令牌来保证的,而且主机运行时仍然可以选择简单地拒绝访问基于WASI的函数调用。

Wasm模块通常是纯粹的计算,要么没有副作用,要么是由主机运行时严格控制的副作用。浏览器运行时允许的副作用包括通过垫片访问JavaScript API,以及操纵DOM的能力(也是通过通常由代码生成工具创建的代理代码)。

总结

WebAssembly只存在了几年时间,不管我们是否意识到,它已经出现在我们的每一个浏览器中。像Fastly和CloudFlare这样的公司正在试验在边缘运行WebAssembly,而在我的下一篇文章中,我将会谈论无数行业如何在云中使用WebAssembly。

我们长期以来一直认为计算的圣杯--小尺寸、可移植性、安全性、性能--都是我们用WebAssembly得到的东西,我希望,如果你还没有,你出去开始玩这个新技术,因为它很可能会发展成为我们未来作为软件开发者的一切。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值