热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

WebAssembly系列(四)WebAssembly事情道理

作者:LinClark编译:胡子大哈翻译原文:http:huziketang.comblogpostsdetail?postId58c77641a6d8a07e449fdd

作者:Lin Clark

编译:胡子大哈

翻译原文:http://huziketang.com/blog/posts/detail?postId=58c77641a6d8a07e449fdd24

英文原文:Creating and working with WebAssembly modules

转载请申明出处,保存原文链接以及作者信息

本文是关于 WebAssembly 系列的第四篇文章(本系列共六篇文章)。假如你没有读先前文章的话,发起先读这里。假如对 WebAssembly 没观点,发起先读这里(中文文章)。

WebAssembly 是除了 Javascript 之外,另一种可以在网页中运转的编程言语。过去假如你想在浏览器中运转代码来对网页中种种元素举行掌握,只需 Javascript 这一种挑选。

所以当人们议论 WebAssembly 的时刻,往往会拿 Javascript 来举行比较。然则它们实在并非“二选一”的关联——并非只能用 WebAssembly 或许 Javascript。

现实上,我们勉励开辟者将这两种言语一同运用,纵然你不亲身完成 WebAssembly 模块,你也可以进修它现有的模块,并它的上风来完成你的功用。

WebAssembly 模块定义的一些功用可以经由历程 Javascript 来挪用。所以就像你经由历程 npm 下载 lodash 模块并经由历程 API 运用它一样,将来你也可以下载 WebAssembly 模块而且运用其供应的功用。

那末就让我们来看一下怎样开辟 WebAssembly 模块,以及怎样经由历程 Javascript 运用他们。

WebAssembly 处于哪一个环节?

在上一篇关于汇编的文章中,我引见了编译器是怎样从高等言语翻译到机械码的。

《WebAssembly 系列(四)WebAssembly 事情道理》

那末在上图中,WebAssembly 在什么位置呢?现实上,你可以把它算作另一种“目标汇编言语”。

每一种目标汇编言语(x86、ARM)都依赖于特定的机械构造。当你想要把你的代码放到用户的机械上实行的时刻,你并不晓得目标机械构造是什么样的。

而 WebAssembly 与其他的汇编言语不一样,它不依赖于详细的物理机械。可以抽象地明白成它是观点机械的机械言语,而不是现实的物理机械的机械言语。

正由于如此,WebAssembly 指令偶然也被称为假造指令。它比 Javascript 代码更直接地映射到机械码,它也代表了“怎样能在通用的硬件上更有效地实行代码”的一种理念。所以它并不直接映射成特定硬件的机械码。

《WebAssembly 系列(四)WebAssembly 事情道理》

浏览器把 WebAssembly 下载下来,然后先经由 WebAssembly 模块,再到目标机械的汇编代码。

编译到 .wasm 文件

如今关于 WebAssembly 支撑状况最好的编译器东西链是 LLVM。有很多差别的前端和后端插件可以用在 LLVM 上。

提醒:很多 WebAssembly 开辟者用 C 言语或许 Rust 开辟,再编译成 WebAssembly。实在另有其他的体式格局来开辟 WebAssembly 模块。比方应用 TypeScript 开辟 WebAssembly 模块,或许直接用 WebAssembly 文本也可以。

假定想从 C 言语到 WebAssembly,我们就须要 clang 前端来把 C 代码变成 LLVM 中间代码。当变更成了 LLVM IR 时,申明 LLVM 已明白了代码,它会对代码自动地做一些优化。

为了从 LLVM IR 天生 WebAssembly,还须要后端编译器。在 LLVM 的工程中有正在开辟中的后端,而且应当很快就开辟完成了,如今这个时候节点,临时还看不到它是怎样起作用的。

另有一个易用的东西,叫做 Emscripten。它经由历程本身的后端先把代码转换成本身的中间代码(叫做 asm.js),然后再转化成 WebAssembly。现实上它背地也是运用的 LLVM。

《WebAssembly 系列(四)WebAssembly 事情道理》

Emscripten 还包含了很多分外的东西和库来包涵全部 C/C++ 代码库,所以它更像是一个软件开辟者东西包(SDK)而不是编译器。比方体系开辟者须要文件体系以对文件举行读写,Emscripten 就有一个 IndexedDB 来模仿文件体系。

不斟酌太多的这些东西链,只需晓得终究天生了 .wasm 文件就可以了。背面我会引见 .wasm 文件的构造,在这之前先一同相识一下在 JS 中怎样运用它。

加载一个 .wasm 模块到 Javascript

.wasm 文件是 WebAssembly 模块,它可以加载到 Javascript 中运用,现阶段加载的历程轻微有点庞杂。


function fetchAndInstantiate(url, importObject) {
return fetch(url).then(respOnse=>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results =>
results.instance
);
}

假如想深切相识,可以在 MDN 文档中相识更多。

我们一直在致力于把这一历程变得简朴,对东西链举行优化。愿望可以把它整合到现有的模块打包东西中,比方 webpack 中,或许整合到加载器中,比方 SystemJS 中。我们置信加载 WebAssembly 模块也可以像加载 Javascript 一样简朴。

这里引见 WebAssembly 模块和 Javascript 模块的重要区分。当前的 WebAssembly 只能运用数字(整型或许浮点型)作为参数或许返回值。

《WebAssembly 系列(四)WebAssembly 事情道理》

关于任何其他的庞杂范例,比方 string,就必需得用 WebAssembly 模块的内存操纵了。假如是常常运用 Javascript,对直接操纵内存不是很熟悉的话,可以追念一下 C、C++ 和 Rust 这些言语,它们都是手动操纵内存。WebAssembly 的内存操纵和这些言语的内存操纵很像。

为了完成这个功用,它运用了 Javascript 中称为 ArrayBuffer 的数据构造。ArrayBuffer 是一个字节数组,所以它的索引(index)就相当于内存地址了。

假如你想在 Javascript 和 WebAssembly 之间通报字符串,可以应用 ArrayBuffer 将其写入内存中,这时刻 ArrayBuffer 的索引就是整型了,可以把它通报给 WebAssembly 函数。此时,第一个字符的索引就可以当作指针来运用。

《WebAssembly 系列(四)WebAssembly 事情道理》

这就彷佛一个 web 开辟者在开辟 WebAssembly 模块时,把这个模块包装了一层外套。如许其他运用者在运用这个模块的时刻,就不必体贴内存治理的细节。

假如你想相识更多的内存治理,看一下我们写的 WebAssembly 的内存操纵。

.wasm 文件构造

假如你是写高等言语的开辟者,而且经由历程编译器编译成 WebAssembly,那你不必体贴 WebAssembly 模块的构造。然则相识它的构造有助于你明白一些基本问题。

假如你对编译器还不相识,发起先读一下“WebAssembly 系列(三)编译器怎样天生汇编”这篇文章。

这段代码是行将天生 WebAssembly 的 C 代码:

int add42(int num) {
return num + 42;
}

你可以运用 WASM Explorer 来编译这个函数。

翻开 .wasm 文件(假定你的编辑器支撑的话),可以看到下面代码:

00 61 73 6D 0D 00 00 00 01 86 80 80 80 00 01 60
01 7F 01 7F 03 82 80 80 80 00 01 00 04 84 80 80
80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06
81 80 80 80 00 00 07 96 80 80 80 00 02 06 6D 65
6D 6F 72 79 02 00 09 5F 5A 35 61 64 64 34 32 69
00 00 0A 8D 80 80 80 00 01 87 80 80 80 00 00 20
00 41 2A 6A 0B

这是模块的“二进制”示意。之所以用引号把“二进制”引起来,是由于上面现实上是用十六进制示意的,不过把它变成二进制或许人们能看懂的十进制示意也很轻易。

比方,下面是 num + 42 的种种示意要领。

《WebAssembly 系列(四)WebAssembly 事情道理》

代码是怎样事情的:基于栈的假造机

假如你对详细的操纵历程很猎奇,那末这幅图可以通知你指令都做了什么。

《WebAssembly 系列(四)WebAssembly 事情道理》

从图中我们可以注意到 操纵并没有指定哪两个数字举行加。这是由于 WebAssembly 是采纳“基于栈的假造机”的机制。即一个操纵符所须要的一切值,在操纵举行之前都已存放在客栈中。

一切的操纵符,比方加法,都晓得本身须要多少个值。 须要两个值,所以它从客栈顶部取两个值就可以了。那末指令就可以变的更短(单字节),由于指令不须要指定源寄存器和目标寄存器。这也使得 .wasm 文件变得更小,进而使得加载 .wasm 文件更快。

只管 WebAssembly 运用基于栈的假造机,然则并非说在现实的物理机械上它就是这么见效的。当浏览器翻译 WebAssembly 到机械码时,浏览器会运用寄存器,而 WebAssembly 代码并不指定用哪些寄存器,如许做的优点是给浏览器最大的自由度,让其本身来举行寄存器的最好分派。

WebAssembly 模块的组成部份

除了上面引见的,.wasm 文件另有其他部份,一般把它们叫做部件。一些部件关于模块来说是必需的,一些是可选的。

必需部份

  1. Type。在模块中定义的函数的函数声明和一切引入函数的函数声明。

  2. Function。给出模块中每一个函数一个索引。

  3. Code。模块中每一个函数的现实函数体。

可选部份

  1. Export。使函数、内存、表单(table)、全局变量等对其他 WebAssembly 或 Javascript 可见,许可动态链接一些离开编译的组件,即 .dll 的WebAssembly 版本。

  2. Import。许可从其他 WebAssembly 或许 Javascript 中引入指定的函数、内存、表单或许全局变量。

  3. Start。当 WebAssembly 模块加载进来的时刻,可以自动运转的函数(类似于 main 函数)。

  4. Global。声明模块的全局变量。

  5. Memory。定义模块用到的内存。

  6. Table。使得可以映射到 WebAssembly 模块之外的值,如映射到 Javascript 对象中。这在间接函数挪用时很有效。

  7. Data。初始化内存。

  8. Element。初始化表单(table)。

假如想要相识更多的部件,可以在“怎样运用部件”中深切相识。

下文预报

如今你已相识了 WebAssembly 模块的事情道理,下面将会引见为何 WebAssembly 运转的更快。

我近来正在写一本《React.js 小书》,对 React.js 感兴趣的童鞋,迎接指导。


推荐阅读
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 本文介绍了在Ubuntu 11.10 x64环境下安装Android开发环境的步骤,并提供了解决常见问题的方法。其中包括安装Eclipse的ADT插件、解决缺少GEF插件的问题以及解决无法找到'userdata.img'文件的问题。此外,还提供了相关插件和系统镜像的下载链接。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • Python实现变声器功能(萝莉音御姐音)的方法及步骤
    本文介绍了使用Python实现变声器功能(萝莉音御姐音)的方法及步骤。首先登录百度AL开发平台,选择语音合成,创建应用并填写应用信息,获取Appid、API Key和Secret Key。然后安装pythonsdk,可以通过pip install baidu-aip或python setup.py install进行安装。最后,书写代码实现变声器功能,使用AipSpeech库进行语音合成,可以设置音量等参数。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 本文介绍了作者在开发过程中遇到的问题,即播放框架内容安全策略设置不起作用的错误。作者通过使用编译时依赖注入的方式解决了这个问题,并分享了解决方案。文章详细描述了问题的出现情况、错误输出内容以及解决方案的具体步骤。如果你也遇到了类似的问题,本文可能对你有一定的参考价值。 ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • C++程序员视角下的Rust语言
    自上世纪80年代初问世以来,C就是一门非常重要的系统级编程语言。到目前为止,仍然在很多注重性能、实时性、偏硬件等领域发挥着重要的作用。C和C一样&#x ... [详细]
  • 痞子衡嵌入式:对比MbedTLS算法库纯软件实现与i.MXRT上DCP,CAAM硬件加速器实现性能差异...
    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是MbedTLS算法库纯软件实现与i.MXRT上DCP,CAAM硬件加速器实现性能差异。近 ... [详细]
author-avatar
小呆74588
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有