WebAssembly编译之(1)-asm.js及WebAssembly原理介绍

news2025/1/17 0:23:01

WebAssembly介绍及产生历程

1、什么是WebAssembly、为什么WASM?

我们知道Web的应用几乎涵盖了大半个互联网应用;越多越多的Web应用层出不穷,而然Web最致命的劣势就是其在浏览其的运行效率特忙,尤其是web游戏的体验不佳。

而WebAssembly(即WASM)可以解决这个问题,WASM是一种可运行在浏览器的格式,它可移植、体积小、加载快并且兼容 Web 的二进制格式, 其目标就是充分发挥硬件能力以达到原生执行效率;

2、WASM的产生背景

2012年,Mozilla的工程师(Alon Zakai)在研究LLVM时突然想到,如果能将c/c++代码编译成javascript代码,那许c/c++开发的代码都能在浏览器运行了。为此,他专门做了一个编译器项目,这个编译器即Emscripten,而这个编译器编译出来的js即asm.js

asm.js又是啥呢?

asm.js本质就是就Javascript代码,是它的子集,只是asm.js是严格的Javascript代码,在asm.js许多动态变量是不允许使用的。我们知道JS 是动态类型语言,而C是静态类型语言,所以,c/c++转成asm.js需要解决的前提是,采用静态声明;此外,JS是自动内存回收机制的;也就是说asm.js必须同时解决两个关键问题:

  • 静态类型语言
  • 手动内存回收

这就asm.js与普通JS最大区别,我们可以看一下asm.js什么样的,最明显的就是变量的声明定义

var a = 1;

var x = a | 0;  // x 是32位整数
var y = +a;  // y 是64位浮点数

sm.js 就要求事先声明类型,并且不得改变,这样就节省了类型判断的时间。asm.js 的类型声明有固定写法,变量 | 0表示整数,+变量表示浮点数。

看起来一时间好像并没啥不一样啊?我们写正常的JS,在写一段asm.js

// Javascript常规写法
var first = 5;
var second = first;

// asm.js要求的严格静态声明写法
var first = 5;
var second = first | 0;
// 除了参数x和y需要声明类型,函数的返回值也需要声明类型
function add(x, y) {
  x = x | 0;
  y = y | 0;
  return (x + y) | 0;
}
asm.js与WebAssembly有什么不同?

两者的功能基本一致,就是转出来的代码不一样:asm.js 是文本,WebAssembly(wasm) 是二进制字节码,因此运行速度更快、体积更小.

从长远来看,WebAssembly 的前景貌似更光明,因为本身asm.js 尽管是js,但是基本与WebAssembly一样已缺失了可读性,相比WebAssembly文件更小,执行效率更高,所以从这点看WebAssembly更有利。

Javascript 引擎的基本工作原理

Parser(语法词法分析)->AST(语法树)->Interpreter(生成ByteCode)->Profiler(分析可优化代码)->Compiler(生成优化后的Machine Code)

通常ByteCode已经是可执行了的,Profiler是单独的一条并行分析线程同步进行,发现有可优化的,则交个Compiler优化生成Machine Code后,再替换ByteCode;

我们看一下v8引擎的基本工作原理图:
在这里插入图片描述

Ignition:充当Interpreter(解释器), 同时收集 优化编译所需的信息交给TurboFan
TurboFan:充当Compiler(编译器), TurboFan利用Ignition 所收集的类型信息,将 Bytecode 转换为优化的 Machine Code

由于asm是严格模式,基本可跳过语法分析这一步,直接开始编译成汇编语言。这就是asm.js快的原因

据悉asm.js的效率可达源码的50% ,而WebAssembly可达70%

asm.js的升级——WebAssembly

但是,asm.js也有它的优势,尽管缺失可读性,但是,毕竟是文本,还是可读的;最关键的是asm.js是纯JS,所有浏览器都支持不会有兼容性问题

asm.js得到了Mozilla, Google,Microsoft,Applel 的支持,于是再进一步升级,于是就有了WebAssembly

asm.js说到底还是就是让JIT(即时编译)快一点,但是还是需要有ParserCompiler两个过程。而WebAssembly更激进,既然都具备AOT(预编译)了,直接就给你编译成可执行的二进制了,使之成为可直接与Machine Code打交道的汇编语言;

语言在运行之前通常都需要编译,JIT(Just-in-Time,即时编译) 和 AOT(Ahead-of-Time,预编译) 则是最常见的两种编译模式

目前大部分浏览器都支持WASM
在这里插入图片描述

3. Emscripten的编译执行流程

前面我们介绍到Emscripten是个可以把c/c++转成asm.js的编译器(当然也可以转为wasm),而Emscripten本身是一个基于LLVM的项目,也就是说c/c++需要先编译成LLVM的中间代码后,再转为JS代码。

换句话说,理论上所有可以转为LLVM的语言,都可以转为asm.js。

LLVM是什么?

LVM是构架编译器(compiler)的框架系统,LLVM 命名最早源自于底层虚拟机(Low Level Virtual Machine);

https://llvm.org/

架构编译器又是个啥玩意?

一个完整的编译器架构,c/c++的开发程序员熟知的编译器有gcc/g++之类的,而常见的这类预编译器的架构如下:
请添加图片描述

整个编译器的三大部分耦合比较紧密,这就导致gcc一般只能对c/c++进行编译;

而LLVM是个架构编译器,他的编译组成是有一系列组件组成,其架构如下所示:

请添加图片描述前后端是由上框架可知是一种轻松耦合的架构,前端后端统一使用一层中间代码及上图的LLVM IR(LLVM Intermediate Representation)进行交流;这种架构的好处是:

当我们需要支持一种语言的时候,我们只需要拓展一个前端编译器即可,而当我们需要支持一种新的设备或平台时,我们只需要拓展一个后端编译器即可,这就是架构编译器。

什么是Clang?

Clang是LLVM的一个子项目,它是LLVM架构的C/C++/Objective-C编译器前端;正如前面的LLVM架构所描述的一样,Clang是个编译器前端,用于将源代码转为LLVM IR中间代码,其主要流程如下:

源码(C/C++) -> 词法分析 -> 语法分析 -> 语义分析 -> 生成中间代码(LLVM IR)

Clang的重要的特性是编译快速、占内存少,而代码质量还比GCC来得高;此外Clang有一个重要的衍生项目是静态分析工具,能够通过自动分析程序的逻辑,在编译时就找出程序可能的bug,这个功能叫做ARC。

Clang相比GCC有许多优势,可到官网了解更多 https://clang.llvm.org/

至此,我们完成是Emscripten编译流程的所需要的背景知识及可能涉及到的名称,于是我们终于可以开始介绍Emscripten
尼马,都睡着了 还没开始?我还以为快结束了@v@

Emscripten编译流程

实际上经过前面的结束,Emscripten的工作机制已经比较清晰了;就是将C/C++源码转为LLVM IR中间代码,再把中间代码转为asm.js或者WebAssembly二进制即wasm。Emscripten其工作流程为:

C/C++ -> LLVM -> Emscripten -> JavaScript/HTML

所以Emscripten是一基于LLVM架构的编译器,主要是在编译器后端进行处理,原本LLVM架构是将中件代码转为机器相关的目标代码,而Emscripten则是生成一种平台相关的目标代码,这种目标代码即asm.jsWebAssembly(wasm)

整个Emscripten的编译执行流程如下所示:

在这里插入图片描述

asm.js可采用WebGL进行加速执行,这也就是为什么asm.js执行会快很多!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/178306.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ubuntu安装Espeak实现tts文字转语音

目录参考一、介绍二、安装安装包安装查看安装版本和espeak-data路径直接尝试安装中文包三、生产wav文件四、代码引入参考 ubuntu完美安装espeak支持中文和粤语 不再报错:Full dictionary is not installed for ‘zh’ 一、介绍 **用途:**可识别多语言的朗读软件 …

JavaEE day4 初识CSS

HTML如果说是前端网页中的骨架 那么CSS就是用来对骨架进行排版美化的、 CSS全称为 Cascading Style Sheets 层叠样式表 预备知识: html中的所有元素都有两个通用的属性:id和class id:唯一标识符,一个html组成元素中&#xff…

Day07 C++STL入门基础知识四——vector容器(上) 基本概念-构造函数-赋值操作-容量大小【全面深度剖析+例题代码展示】

Leave no stone unturned. 竭尽全力 文章目录1. 基本概念1.1 功能1.2 与普通数组相同点与不同点1.3 动态扩展2. 构造函数2.1 功能描述2.2 函数原型2.3 代码展示3. 赋值操作3.1 函数原型3.2 代码展示4. 容量及大小4.1 函数原型4.2 代码展示4.2.1 empty()4.2.1.1 代码展示4.2.1.2…

恶意代码分析实战 1 静态分析基础技术

1.1 Lab 1-1 对Lab01-01.exe和Lab01-01.dll进行分析 问题 将文件上传至http://www.VirusTotal.com进行分析并查看报告。文件匹配到了已有的反病毒软件特征吗? 首先查看Lab-01-01.exe。 然后查看Lab01-01.dll。 这两个文件应该都是恶意文件。 这些文件是什么时候编译的?…

20230125英语学习

Office Buzzwords You’re Using That Annoy All Your Co-workers 说话之道:避开办公室行话的“雷区” Joining a new office means having to learn how to communicate with your team.But in order to do that well, it sometimes means having to learn your …

索引优化示例

目录 1.单表优化 2.两表优化 3.三表优化 4.总结 1.单表优化 创建索引前 (1)先按照where条件创建索引 按照查询条件中的三个项目创建索引,并且索引中的项目存在顺序,分别是1,2和3。 (2)创建索引 type 变成了 range,这是可以忍受的。但是 extra 里使用…

恶意代码分析实战 4 识别汇编中的C代码结构

4.1 Lab06-01.exe 由main函数调用的唯一子过程中发现的主要代码结构是什么? 使用Strings进行查看,需要注意最后的这两个字符串,一个是“没有网”,另一个是“联网成功”。 IDA 中查看图结构。 明显是if-else结构。 位于0x4010…

进程间通信/管道/消息队列/共享内存/信号量

本文重点目标: ⭐进程间通信介绍⭐ ⭐管道⭐ ⭐消息队列⭐ ⭐共享内存⭐ ⭐信号量⭐ 1.进程间通信介绍 什么是通信? 通信指的是数据传输、资源共享、通知事件和进程控制。 ①数据传输:一个进程需要将它的数据发送给另一个进程 ②资源共享&a…

【GIS】高分辨率遥感影像智能解译

1 绪论 随着航空科技工业的不断成熟与发展,我国遥感卫星研制能力不断攀升,发射数量逐年提高,在轨运行的遥感卫星为社会生产及居民日常生活提供了巨大的支持与便利。我国目前同时在轨运行的遥感卫星数量已超过60颗,每天获取并传回…

LeetCode[990]等式方程式的可满足性

难度:中等题目:给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i]的长度为 4,并采用两种不同的形式之一:"ab"或 "a!b"。在这里,a 和 b 是小写字母&#…

【Python学习003】高效数据结构-列表

【Python学习003】高效数据结构-列表 我们的公众号是【朝阳三只大明白】,满满全是干货,分享近期的学习知识以及个人总结(包括读研和IT),希望大家一起努力,一起加油!求关注!&#xf…

浏览器使用本地硬盘上的JS文档

网页通过<script>标记可以引入在线的js文档&#xff0c;只有把网页保存在本地硬盘才能使用相对路径引入本地js文档&#xff0c;普通浏览器难以实现在线页面上引入本地js文档。怎么解决这个问题呢&#xff1f;首先准备好需要引入的JS文档&#xff0c;可以是成熟的JS库&…

【docker概念和实践 4】(3)本地镜像提交到阿里云

一、说明 本篇讲述如何将自己制作的容器转化成镜像&#xff0c;再将镜像推送到远端阿里云上。 二、制造一个本地容器 2.1 从远端仓库拉取ubuntu镜像 使用镜像拉取语句&#xff1a; docker pull ubuntu:20.04 docker run -it ubuntu&#xff1a;20.04 bash 通过以上两句&…

LeetCode[200]岛屿数量

难度&#xff1a;中等题目&#xff1a;给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外&am…

5-4中央处理器-控制器的功能和工作原理

文章目录一.控制器的结构和功能二.硬布线控制器1.硬布线控制单元图2.微操作命令分析3.CPU的控制方式&#xff08;1&#xff09;同步控制方式&#xff08;2&#xff09;异步控制方式&#xff08;3&#xff09;联合控制方式4.硬布线控制单元的设计步骤&#xff08;1&#xff09;分…

qsort函数用法 + 模拟实现qsort函数

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言学习者 ✈️专栏&#xff1a;【C/C】算法 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞…

论文笔记目录(ver2.0)

1 时间序列 1.1 时间序列预测 论文名称来源主要内容论文笔记&#xff1a;DCRNN &#xff08;Diffusion Convolutional Recurrent Neural Network: Data-Driven Traffic Forecasting&#xff09;_UQI-LIUWJ的博客-CSDN博客iclr 2017使用双向扩散卷积GRU&#xff0c;建模空间和…

目标跟踪心得篇五:MOT数据集标注、TrackEval的使用、DarkLabel不能自动跟踪解决方案及如何在MMTracking上输出跟踪评测

跟踪方向的标注成本非常很大的 ,那么我们如何尽可能一次性弄好呢? 所选标注工具:DarkLabel DarkLabel是一个轻量的视频标注软件,尤其做MOT任务非常友好,其标注可以通过脚本转化为标准的目标检测数据集格式、ReID数据集格式和MOT数据集格式。 使用之前: darklabel.yml:保…

传参的理解

前言 当我们调用函数的时候&#xff0c;参数是怎么传递给被调用方的&#xff0c;有想过这个问题吗&#xff1f;传递不同大小的参数对调用方式有影响吗&#xff1f;本文将带你探究这些问题&#xff0c;阅读本文需要对函数栈帧有一定的理解&#xff0c;并了解基本的汇编指令。 …

傅一平:2022年我的私人书单

2022年过去了&#xff0c;推荐我的TOP 10 书单&#xff0c;同时附上我的一句话评语和豆瓣的评分&#xff0c;这些书代表了我学习的方向&#xff0c;包括学习方法、思考方法、数据治理、数字化转型、系统架构、职场管理、个人修养、生活态度等。TOP 1 学习究竟是什么一句话评语…