WebAssembly作为“技能树”的未来

有人以某种方式误解了WebAssembly。 有些人认为,由于浏览器已经支持WebAssembly(自2017年起),因此一切就绪。 尚未关闭,只有MVP(最低可行产品)已经准备就绪。 我可以猜测出此错误的根源:在MVP发布之后,其开发人员承诺将向后兼容性保持在“现在编写的任何代码将来都可以使用”的水平。 但这并不意味着WebAssembly的开发已经完成,甚至根本没有完成! 目前正在开发许多功能,并计划在不久的将来进行开发。 当实施它们时,一切都会发生很大变化。

您可以尝试在某些游戏中以技能树的形式想象所有这些功能。 我们有几个“基本”(已实现的功能)和一棵带有许多分支和叶子的整棵树,随着时间的流逝,它们将不断开放,从而赋予我们越来越多的力量。
图片
让我们看一下我们已经拥有的东西以及我们仍然需要发现的东西。
下切了很多图片,交通

最低可行产品(MVP)


图片
Emscripten是WebAssembly的历史的开始,它使将C ++代码编译为JavaScript代码成为可能。 这使我们能够将大量C ++库转移到Web领域,否则就无法运行更高级别的代码。 生成的JS代码远非理想,并且工作缓慢(与本机版本相比)。 但是,Mozilla工程师仍然找到了两种方法来使其更快。 最主要的是分配一种语言子集,该子集的执行速度可与本机代码执行速度相媲美。 该子集称为asm.js。

其他浏览器的开发人员注意到并赞赏asm.js的速度,所有主流浏览器均获得了其支持。 但这并没有结束故事。 那仅仅是开始。 仍有空间可以更快地工作。 但是他们已经超越了Javascript。 原来,本机代码(例如,在C ++中)必须不是用Javascript编译,而是用其他方式编译。 引入了一些新内容,专门创建为JS的快速替代。 这样WebAssembly就诞生了。

WebAssembly的第一个版本中包含什么? 什么足以获得“最小可行产品”的荣誉称号?

技能:目标编译器平台


图片

从事WebAssembly工作的程序员了解,他们的任务不仅仅是支持C或C ++。 任务是提供机会以WebAssembly中的任何语言编译代码。 应该是这样的“汇编程序”,它应该在浏览器中执行,就像在x86平台上执行桌面应用程序的机器代码一样。 但是,这种新语言不应依赖任何特定平台,其目标应该是更高级别的抽象平台,其特定实现将已经取决于此硬件上使用的指令集。

技能:快速执行代码


图片

一切都必须快速进行。 否则,为什么还要打扰整个故事呢? 最后,用户应该能够运行真正的“繁重”应用程序,能够在浏览器中玩顶级游戏,等等。

技能:紧凑


图片

不仅重要的是代码执行的速度,而且它的加载速度也很重要。 用户习惯了启动速度非常快的桌面应用程序(因为它们是本地安装的,并且拥有所有必要的资源)。 Web应用程序也运行相对较快,因为它们不会一次加载太多资源。 这对我们提出了新的挑战:如果我们要创建一种新型的Web应用程序,其代码库与经典的桌面应用程序一样大,但可以从Internet下载,则代码应尽可能紧凑。

技能:内存访问


图片

我们的新应用程序还需要以与JavaScript代码稍有不同的方式来处理内存。 需要直接访问存储块。 这是由于C和C ++语言的特殊性,其中存在指针。 粗略地说,指针是一个包含内存中地址的变量。 应用程序可以在该地址读取数据,对其进行更改,甚至可以使用算术运算符的指针从指定地址向前“遍历”内存。 大量的C / C ++代码使用指针来提高其工作效率,如果没有指针的支持,就不可能为此类代码创建目标平台。

但是我们不能允许从Internet下载的任何代码直接访问过程的内存-这太危险了。 我们将不得不创建一个环境,一方面,该环境将允许WebAssembly中编译的本机代码相信它具有直接的内存访问权限,但另一方面,它将严格限制允许其操作数据的区域。

为此,WebAssembly使用“线性内存模型”。 这是使用TypedArrays实现的-与JavaScript中的数组类似,但仅在内存中包含一组连续的字节。 当您想在其中放置内容时,可以使用按索引访问元素(可以是内存中的地址)。 因此,此数组“假装”为C ++代码的内存块。

新成就!


因此,通过上述所有操作,人们最终将能够在浏览器中以与本地应用程序几乎相同的性能运行桌面应用程序。 关于此功能集,被称为“最小可行产品”(MVP)。

图片

此时,确实可以在WebAssembly下构建某些应用程序并在浏览器中赚钱。 但是还有很长的路要走。

重量级桌面应用程序


图片

下一个重要步骤应该是启动真正的大型桌面应用程序的能力。 您能想象在浏览器中运行的完整版Photoshop吗? 而且您没有安装它,只需打开链接-现在您可以在任何设备上以本机速度拥有该产品的所有100%功能,最新版本以及所有更新和修复。

而且我们离这个还很远-例子已经开始出现。 例如,AutoCAD。 还有Adobe Lightroom。 但是,老实说-在WebAssembly的当前实现中,并不是所有事情都可以启动真正的大型应用程序。 当您阅读本文时,此时就在这里调查并纠正瓶颈。

技能:多线程


图片

显然,我们需要多线程。 现代计算机具有许多核心。 我们需要能够使用它们。

技能:SIMD


图片

除了多线程之外,还有另一种技术可以更有效地实现并行数据处理。 这就是SIMD:通过一条指令一次处理多个数据块。 真正快速的WebAssembly必需​​的重要方面。

技能:64位寻址


图片

WebAssembly中尚不可用的现代硬件体系结构的另一个重要功能是对64位内存寻址的支持。 一切都很简单:使用32位地址只能使用4 GB的内存(对于大型程序来说这是很小的),但是对于64位地址,它已经可以达到16艾字节(对于现代软件来说这是很多)。 当然,不仅理论上的最大值很重要,实用上的最大值(操作系统将为您提供多少内存)也很重要。 但是在大多数现代设备上,已经有4 GB或更多GB的RAM,并且这个数目会增加。

技能:流编译


图片

我们不仅需要快速执行应用程序。 我们还需要缩短从网络开始下载到开始下载之间的时间间隔。 流编译使您可以在最终下载WebAssembly文件之前开始对其进行处理。 我们会审查通过网络下载的说明。 因此,加载和编译是并行进行的。 在Firefox代码中,我们能够实现高于下载速度的编译速度-也就是说,事实证明,某些N字节代码的处理时间少于该代码在网络上的下载时间。 其他浏览器的开发人员也在从事流编译。

图片

与流式编译有关的一件事是使用两个编译器 。 其中之一(如上所述)可以快速运行,并允许您立即启动下载的代码。 但是,他并没有执行所有理论上可能的优化,因为这需要更多时间。 此类优化由在后台工作的另一个编译器执行。 他完成工作后,内存中的一个版本会替换另一个版本,然后改为工作。

因此,我们既可以快速启动该应用程序,又可以使其有效运行。

技能:缓存


图片

如果我们曾经通过优化的编译器下载并编译了一些WebAssembly代码,那么在另一个选项卡中加载此代码(或在应用程序保持不变的情况下,下次打开浏览器)时执行相同的操作是没有意义的。 可以(并且应该)缓存已编译的代码,然后从缓存中使用它。

技能:其他改进


图片

现在有很多讨论,关于还有哪些其他可能的改进,以及应该关注开发人员的努力。 肯定会实现某些事情,不会立即实现的事情,根本不会发生的事情。 在您的允许下,我将在通用类“其他改进”中定义所有这些要点,随着时间的推移我们将了解其中的内容。

我们现在在哪里?


在此附近:

图片

多线程


对于多线程,我们有一个几乎已经准备好的计划 ,但是它的关键部分之一( SharedArrayBuffers )在今年年初被迫禁用 。 它将很快重新打开,我们可以继续。

SIMD


现在积极发展

64位寻址


对于wasm-64 ,我们对事情应该如何工作有一个非常清晰的想法。 我们基于x86和ARM体系结构方法。

流编译


在Firefox中,它是在2017年添加的 ,其他浏览器都在使用它。

使用两个编译器


在Firefox中,此功能于2017年添加,在2018年的其他浏览器中已添加。

隐式HTTP缓存


在Firefox中,开发工作已接近完成 ,即将发布。

其他改进


有一个讨论

如您所见,大多数项目仍在积极开发中。 尽管如此,我们今天已经可以在WebAssembly上看到运行的应用程序,因为对于某些人来说,今天的功能已经足够了。 一旦上述所有功能都准备就绪,我们将开启另一个“新成就”,甚至更多新应用程序将获得WebAssembly支持。

图片

JavaScript互动


图片

WebAssembly不仅是作为游戏和大量应用程序的平台而创建的。 它可以用于常规的Web开发。 我们知道,今天有非常大的用Javascript编写的Web应用程序,很少有人决定采用并将它们完全重写为WebAssembly。 这里的重点是,这不是必需的。 最有可能的是,这些应用程序中的大多数都能很好地运行,并且仅在某些瓶颈上运行,也许是由于缺少某些库的JS版本而导致计算性能,数据处理带宽或功能缺乏。 我们希望使开发人员有机会仅在WebAssembly上重写这些瓶颈,而将其余代码保留在熟悉的JS中。 而且这已经成为可能。 例如,通过将Gutenberg解析器重写为Rust并在WebAssebly下进行组装,我们成功实现了86倍的生产率提高。

但是,为了使这种做法既方便又方便,我们需要执行其他措施。

技能:JS和WebAssembly之间的快速调用


图片

从JS调用WebAssembly应该很快。 通过添加一个小的WebAssembly模块,即使经常调用此模块,程序员也不会感到任何性能损失。 在MVP中不是这种情况(因为MVP的目标不是最大化此类调用的性能)。 这个问题尚未解决。 在Firefox中,我们已经确保某些JS-> WebAssembly调用已经比非内联JS-> JS调用快 。 其他浏览器的开发人员也正在从事此任务。

技能:快速数据交换


图片

该任务与上一个任务有关:不仅重要的是从JS快速调用WebAssembly代码,而且要在它们之间快速传输数据。 这有某些问题。 例如,WebAssembly仅理解数字这一事实。 其中没有对象,但是在JS中是。 事实证明,我们需要某种翻译层。 它已经存在,但仍然不够高效。

技能:与ES模块集成


图片

现在,使用WebAssembly模块就像调用一个特殊的API,它将使该模块返回给您使用。 但这意味着WebAssembly模块并不是Web应用程序的JS模块图的真正组成部分。 为了使所有功能都可用于ES模块(例如导出和导入),WebAssembly模块必须能够与ES模块集成。

技能:开发整合


图片

能够导入和导出并不意味着成为功能齐全的模块。 我们需要一个可以分发WebAssembly模块的地方。 WebAssembly的npm类似于什么? 嗯... npm本身怎么样? 以及用于WebAssembly的webpack或Parcel的类似物是什么? 嗯... webpack和Parcel呢?

WebAssembly模块不应与普通模块不同,这意味着它们可以通过相同的基础结构进行分发。 但是我们需要工具将它们集成到此基础架构中。

技能:向后兼容


图片

我们还必须提供另一件重要的事情。 即使在较旧版本的浏览器中,一切也应能正常工作。 甚至那些对WebAssembly都不了解的人。 我们必须保证,一旦我们为WebAssembly编写了代码,开发人员就不必仅仅因为该站点也必须在IE11中打开而用Javascript编写同一代码的第二版本。

我们现在在哪里?


在这里的某处:
图片

JS和WebAssembly之间的快捷方式


已经在Firefox中实现 ,正在其他浏览器中进行工作。

快速数据交换


有几个建议。 例如,使用对JS对象的引用来扩展WebAssembly中的类型系统。 这是可能的,但是将需要编写额外的代码(例如,调用JS方法),但这不会太快。 为了解决这个问题,反过来有一些建议。

还有另一方面涉及数据交换。 这是关于跟踪数据可以在内存中存储多长时间。 如果内存中有JS代码应有权访问的任何数据,则必须将其保留在那里,直到JS代码读取它为止。 但是,如果您将它们永远留在那里,那么我们将发生内存泄漏。 如何找出可以删除的数据(JS代码已经读取了它们)? 如今,程序员应承担责任-一切都是手动发布。 JS代码完成数据读取后,应调用诸如“ free”功能之类的东西。 但是这种方法已经过时,并经常导致错误。 为了解决这个问题,我们在Javascript中引入了WeakRef的概念。 这样就可以读取JS代码方面的数据,并且当垃圾回收器工作时,必须正确清除WebAssembly模块中的内存。

所有这一切仍在开发中。 同时已在Rust生态系统中创建工具 ,可以自动为您编写此类代码,并用自己的实现替换尚未实现的部分。 这些工具之一值得特别提及。 它称为wasm-bindgen 。 当他注意到您的Rust代码正在尝试获取或返回JS对象或DOM对象时,它会自动创建一个能够与您的Rust代码进行交互的JS层。 而且该层还能够与以任何其他语言编写的WebAssembly模块进行交互,因此不仅Rust程序员可以使用此工具。

与ES模块集成


这个领域的工作计划已经存在了很长一段时间。 我们正在与其他浏览器的开发人员一起积极地努力。

开发整合


已经有Rust生态系统中的wasm-pack之类的工具,可以让您自动打包需要在npm中发布的所有内容。 有人使用此工具来创建他们的模块。

向后兼容


为了向后兼容,我们提供了wasm2js工具。 它允许您将wasm文件转换为等效的JS文件。 此Javascript代码不会很快,但可以在任何浏览器(包括不支持WebAssembly的浏览器)上运行。

如您所见,我们非常接近接受这一“成就”。 一旦我们做到这一点,通往另外两个道路的道路就会打开。
图片

JS框架和JS编译语言


第一个是在WebAssebly上重写流行的重量级JS框架的功能。

图片

第二个方法是启用以Javascript编译的编程语言,以将其替换为WebAssembly。 我们正在谈论诸如Scala.jsReasonElm之类的语言。

图片

对于这两项任务,WebAssembly必须支持许多新的高级功能。

技能:垃圾收集器


图片

由于多种原因,我们需要与基于浏览器的垃圾收集器集成。 首先,让我们回顾一下重写JS框架(或其一部分)的任务。 可能需要。 , React DOM-, Rust . - . DOM , , . , , , . , .

JS-. - , . , , Javascript. JS- WebAssembly-, JS-.

( ), . , , . WebAssembly , .

Scala.js, Reason, Kotlin Elm — Javascript, . WebAssembly — WebAssembly ( ).

:


图片

. , , Rust, . — . — . WebAssembly .

, Javascript. — - - . WebAssembly- JS-, — . Rust, , . , .

:


图片

, JS-, . Javascript-. WebAssembly.

:


图片

, " ". , — . , WebAssembly.

?


- :

图片


为了实现垃圾收集,目前正在进行两个方向的工作:这是JS的类型化对象 ,实际上是WebAssembly的垃圾收集器 。 带类型的对象使您能够描述对象的清晰结构。 已经有关于如何工作的愿景,将在即将举行的TC39会议上进行讨论。 因此,WebAssembly的GC将能够出于自己的目的访问上述结构。 实施工作已经在进行中。

这两部分都完成后,我们将通过JS和WebAssembly交互获得一个系统,该系统能够在各个级别上了解对象由什么组成并有效地使用其内部数据。 我们已经有了一个可行的原型。 但是,该原型不能随便取用和发布-我们必须花一些时间进行标准化和修订。 我们预计它将在2019年发布。

异常处理


当前正在研究例外情况 。 我们考虑各种建议,尝试执行它们,并查看它们如何有效地工作。

侦错


对于调试,Firefox开发人员工具中已经提供了一些支持。 但是理想还很遥远。 我们希望向开发人员展示其源代码和当前位置,而不仅仅是汇编程序指令。 我们必须开发并实现对符号文件的支持,这将使我们能够将每个代码指令与源代码行相关联。 目前,有关此机制的规范正在进行中

尾声


正在进行中

完成以上所有操作后,我们可以假定我们已经实现了“将JS框架和语言编译成JS”的成就。

图片

因此,这是在浏览器中获得“成就”的计划。 在浏览器之外发生了什么?

浏览器外


也许您对“浏览器外部”一词的组合感到尴尬。 当我们谈论网络时,除了浏览器之外,我们真的还有什么吗? 但是“ Web”的名称恰好是“ WebAssembly”。 但实际上,HTML,CSS和JavaScript只是冰山一角。

图片

是的,它们是最可见的,因为它们是用户界面的形成。 但是网络还有另一个非常重要的部分-连接。 一切与一切的联系。

图片

我现在可以链接到您的页面。 我不需要您或任何其他人的许可。 我只是创建此链接,并将其添加到我的网站。 任何人都可以关注它,并且您的内容将显示,您编写的代码将启动。 创建连接和通过它们进行转换的这种简单性已经创建了我们的Internet。 现在,我们有了社交网络和其他站点,这些站点从本质上扩展了“链接”的概念,并具有对接任何事物的能力:人员,设备,企业等。

但是对于所有这些链接和链接,存在两个问题。

首先,链接应该指向什么? 如果您去某个地方,并且该站点为您提供了一些必须在浏览器中执行的代码-该代码应该是跨平台的。 它应该编译成某种东西,然后在Windows上的android上的poppy上运行。 无处不在。 可下载代码的可移植性是Web连接概念的重要组成部分。

图片

但是仅仅下载并运行代码是不够的。 您需要了解我们对此代码一无所知。 我们对他的信任不足,无法完全控制用户的计算机。 如果是恶意代码怎么办? 他可以做坏事。 在这里,我们需要某种安全模型。 我们需要一个沙箱,我们可以在其中放置一个陌生的代码,为它提供一些受控的工作工具,但要从中删除所有至关重要的和不安全的东西。

图片

因此,“通信”概念有两个方面:可移植性和安全性。 我们知道我们绝对可以运行代码,并且肯定不会损害我们的利益。 我为什么要坚持这些概念?这种事物的观点与HTML,CSS和Javascript的组合与网络的观点有何不同? 因为这种方法从根本上改变了WebAssembly的观点。

一方面,我们可以将WebAssembly视为“现代浏览器中可用的另一种工具”。 就是这样。

图片

但是,代码执行的可移植性和安全性为我们打开了其他大门。

图片

Node.js


图片

WebAssembly如何帮助Node? 带来便携性。

Node通过使用Javascript提供了相当高的可移植性。 但是,仍然有很多情况下JS代码的性能不够,或者尚未编写正确的JS代码,但是存在本机版本。 然后,Node使用本机模块。 它们用C之类的语言编写,并且需要针对运行Node的特定平台进行编译。

本机模块可以在安装过程中进行编译,也可以立即将其用于流行的平台之一。 两种方法都是可行的,但这只是两个弊端的选择:要么让用户感到头疼,要么让模块的创建者感到头疼。

如果您想象这些模块将在WebAssembly上,那么它们根本就不需要编译。 可移植性使您可以立即在任何平台上运行它们,例如Javascript代码。 但是它们将与本机版本的性能一起使用。

在这里,幸福以所有事物和任何地方的完全可移植性的形式出现在Node的世界中。 您可以将Node应用程序从Linux移植到Windows-一切将继续工作,而无需重新编译。 但同时,WebAssembly模块无法访问系统资源(它在其沙箱中工作)。 但是本机(甚至非本机)Node模块无法在沙箱中工作,它们可以访问所有内容-这是Node的思想。 因此,为了使WebAssembly模块获得相同的功能,需要对OS资源进行附加访问。 类似于POSIX功能(它们不是必需的,它们仅作为一个相对稳定和足够的资源访问接口的示例提供)。

技能:便携式界面


图片

那么,Node开发人员需要使用WebAssembly模块什么呢? 某种访问其功能的接口。 标准化它会很好。 好吧,这样Node不仅可以调用这些函数,而且任何人都可以调用这些函数。 如果您想在应用程序中使用WebAssembly模块,我们已经连接并正在使用它。 类似于“ POSIX for WebAssembly”。 PWSIX(便携式WebAssembly系统界面)?

我们现在在哪里?


有一个文档描述了通过其名称提供模块路径的机制。 浏览器和Node都可能会使用它(它们将能够提供不同的路径)。 虽然没有积极的发展,但是有很多讨论。

图片

它很可能将以某种形式实施。 这很好,因为它为我们带来了许多可能性。
图片

CDN,无服务器和边缘计算


图片

例如CDN,无服务器,边缘计算。 将代码放在其他人的服务器上时的情况,这会照顾到客户端的可用性。 为什么这里需要WebAssembly? 最近,有一个关于该主题的出色报告 。 简而言之,可能有必要在一个进程中运行来自不同(互不信任)源的代码。 此代码需要彼此隔离,也应与操作系统隔离。 诸如JS虚拟机(SpiderMonkey或V8)之类的解决方案在某种程度上可以工作,但不能提供所需的性能和可伸缩性。 和WebAssembly-提供。

使这项工作需要什么?

技能:运行时


图片

我们需要一个运行时环境,一些公司创建了自己的环境。 我们已经有了WebAssembly编译器(例如Cranelift )-它们快速且内存有效。 但是他生成的代码不能存在于真空中-他需要依靠某种东西,以某种方式与环境交互。 现在,某些公司(例如Fastly)自行编写了此运行时环境。 但这不是一个很好的方法-毕竟,许多公司将需要它,并且他们会一次又一次地执行相同的工作。 我们可以做一次,添加到标准中-并为每个人节省大量资源。

我们现在在哪里?


在这里的某处:
图片

目前还没有运行时标准。 这不会阻止实际项目中已经使用的几个独立运行时的存在和正常运行。 例如, WAVM和wasmjit。

我们还计划发布一个基于Cranelift的运行时,称为wasmtime。 一旦我们有了一些标准化和可行的东西,这就是开发许多东西的公开机会,例如...

便携式命令行实用程序


图片

WebAssembly不仅可以在浏览器中使用,而且可以在传统操作系统中使用。 我们不会谈论内核(尽管也有一些胆大妄为的人),但是WebAssembly代码可以在用户模式下工作。 这样就可以创建命令行实用程序,这些实用程序一旦构建,就可以保证与任何OS相同。

物联网


图片

“物联网”通常指低功率设备(例如“智能家居”中的可穿戴设备或各种传感器/控制器)。 可用处理器资源和RAM的限制会对在此处运行JS代码的能力产生负面影响,但WebAssembly则完全不同。 在这种情况下,优化诸如Cranelift之类的编译器和诸如wasmtime之类的运行时程序将大放异彩,因为它们只是为节省资源的任务而编写的。 在绝对极端的情况下,WebAssembly甚至可以将模块编译为目标平台的本机二进制文件。 再说一次,可移植性-今天,所有这些物联网设备都很多,它们都建立在不同的平台上。 使用WebAssembly,您不必担心这一点-开发的代码将随处运行。

结论


让我们回顾一下,再看看我们的“技能树”。
图片

我开始这篇文章时的事实是,有些人不了解为什么WebAssembly尚未完成。 如您现在所了解的-他的道路才刚刚开始。 是的,MVP已经开辟了一些可能性。 我们已经可以在WebAssembly中编译某些内容并在浏览器中运行它。 但是,仍有许多工作要做-支持繁重的应用程序和高级语言所需的一切,替换JS框架以及我所说的“浏览器之外”的所有这些内容。 所有这些准备就绪后,我们将看到一个新的网站。 高性能,更大,更便携。 不再有无法编写在浏览器中执行的软件:游戏,区块链,物联网,命令行实用程序-一切都会开始。

WebAssembly尚未完成。 他才刚刚开始。

Source: https://habr.com/ru/post/zh-CN428347/


All Articles