初探WebAssembly
1.前言
参加完2018年上海的QCon大会,想到了会议中来自Microsoft的朱力旻大佬讲的WebAssembly,感触颇深。
我之前完全没有了解过WebAssembly,之前没有了解的原因也很简单,没有什么实际的应用场景,但工欲善其事,必先利其器。
抱着这样的想法,便开始入坑WebAssembly。
2.Why WebAssembly
2.1 javascript的背景
JavaScript这门由Brendan Eich花了10天创造出来的语言,在如今收到了广泛的应用,同时也因为其缺陷遭受到了业界的一些诟病。的确,这门被仓促的创造出来的语言有很多缺陷。毕竟JavaScript结合了函数式编程和面向对象编程,在JavaScript之前的参考极少。
并且JavaScript发展过于迅速,没有多少时间去调整标准。比如JavaScript的变量是一个动态变量。上一秒这个变量可以是Array,下一秒就变成了一个Number。
JavaScript的语法太过于灵活,这样导致JavaScript在开发大型应用上成为了瓶颈,并且类似于CAD这种网格模型对于性能要求特别高的情况下,JavaScript根本无法胜任。
2.2 社区的补救
例如,微软给出了TypeScript这个解决方案,TypeScript为JavaScript添加了静态类型检查,提升了代码的健壮性。但是最终TypeScript还是要编译成JavaScript来运行。
于是在2013年,为了推动Web性能的发展。WebAssembly的前身asm.js诞生了。下面给个例子。
function asmJS() {
'use asm';
let myInt = 0 | 0;
let myDouble = +1.1;
}
传统的JavaScript的动态变量需要在代码执行的时候,编译器才知道当前变量的类型。我们都知道"use strict",这是JavaScript的严格模式。
通过添加代码 "use strict"来使用严格模式。在严格模式下的JavaScript代码会通过抛出错误的方式来代替原来的静默错误。并且在某些情况下, 严格模式下的代码运行效率会高于"sloppy mode"下的代码。
而上述代码中的"use asm",就是告诉引擎,下面的代码是asm.js的代码。当引擎看到"0 | 0",就会在这行代码运行之前知道,这是一个整形的数据,而不会再去编译一次。而看到"+1.1"就会知道这是一个浮点型的数据。asm.js是JavaScript的一个子集。
并且将JavaScript的动态变量变成了静态变量,代码在运行时,有接近原生的性能。
可能到这里疑问就来了,既然asm.js在运行时已经有了接近native的性能。为什么还会出现WebAssembly这个技术。那是asm.js并不能解决所有的问题。
2.3 asm.js并不能解决所有的问题
为什么说asm.js不能解决所有的问题?拿Microsoft Edge的Javascript引擎举个例子。

上面这张图是ChakraCore引擎的结构。Chakra是Microsoft Edge浏览器开源的Chakra Javascript引擎的核心部分。我们在浏览器中运行的Javascript代码首先会经过编译,解析成AST(AKA抽象语法树),想实操的可以去这里试试。
asm.js及时让其运行性能接近了native,但是仍然需要经过parser这一步。而这一步是整个过程中最费时的一步。这就给asm.js造成了一个瓶颈。
2.4 WebAssembly横空出世
于是2015年,WebAssembly出现了。WebAssembly是一个可移植、体积小、加载快并且即兼容Web的汇编格式。
与asm.js类似的是,WebAssembly拥有静态类型。同时也是编译目标,并且可移植。而不同于asm.js,WebAssembly是汇编格式,代码量小,起步相对较快。而且语法上完全脱离JavaScript。这是WebAssembly官方给出的一个demo,可以去体验一下。
3 WebAssembly快速入门
WebAssembly为什么说是编译的目标。是因为WebAssembly可以将C和C++编译成WebAssembly,用的工具是Emscripten,是一个预编译工具。要进行WebAssembly的编译,需要安装git、cmake、python
假设你是在mac上进行操作的。
3.1 安装
安装WebAssembly工具链。
git clone https://github.com/juj/emsdk.git
cd emsdk
./emsdk install --build=Release sdk-incoming-64bit binaryen-master-64bit
./emsdk activate --build=Release sdk-incoming-64bit binaryen-master-64bit
可能会等的有点久,并且可能会出现cmake没有安装的报错信息。可以使用homebrew安装cmake后,再执行安装操作。
3.2 设置环境变量
在emsdk目录下,运行下列命令。就可以在当前的终端窗口中运行emcc命令了。
source ./emsdk_env.sh --build=Release
3.3 编写C或者C++文件
新建一个C文件,代码如下。
#include <stdio.h>
long factorial(int num) {
if (num <= 0) return 1;
else {
return num * factorial(num - 1);
}
}
int main () {
int num = factorial(10);
printf("The Result: %d \n", num);
}
3.4 利用Emscripten编译代码
然后在相同目录下执行emcc的编译命令,该命令会将C或者C++文件编译成wasm模块。
emcc hello.c -s WASM=1 -o hello.html
其中,hello.c为源文件,-o hello.html是这个命令的输出文件,-s WASM指定输出的格式为wasm,并且版本为1。执行这个文件后,会在目录下生成如下数据。
.
├── hello.c
├── hello.html
├── hello.js
└── hello.wasm
hello.wasm就是经过编译后的C代码的二进制文件。而hello.js则是C语言与JavaScript相互转化的中间代码。执行下面的代码就可以在localhost的8080端口看到我们的C模块在前端的调用和展示。
emrun --no_browser --port 8080 .
然后就可以在浏览器中看到如下的输出。

我们编写的C模块已经可以在浏览器中正常的运行了。这说明我们的WebAssembly编译成功了。
4 在前端项目中使用Wasm
可以参考这篇文章,如何在React项目中直接使用WebAssembly,在这篇文章的项目中可以看到完整的从wasm文件中提取出函数的function,以及清晰的用C实现的函数和用JavaScript实现的函数的运行性能对比。
参考资料
初探WebAssembly的更多相关文章
- emscripten、 WebAssembly,传递字符串给c函数
下面看具体的实例. 下面的代码是一个C函数,实现简单的字符串拼接,然后返回拼接的字符串. #include <stdio.h> #include <string> char* ...
- 【webAssembly系列】webAssembly初探究竟
一.前言 自从JavaScript诞生开始,到现在开始变成流行的编程语言,背后的是web发展所推动的.web应用的变得更多更复杂,但是渐渐暴露出JavaScript的问题: (1)语法太灵活导致开发大 ...
- ASP.NET Core Blazor 初探之 Blazor WebAssembly
最近Blazor热度很高,传说马上就要发布正式版了,做为微软脑残粉,赶紧也来凑个热闹,学习一下. Blazor Blazor是微软在ASP.NET Core框架下开发的一种全新的Web开发框架.Bla ...
- ASP.NET Core Blazor 初探之 Blazor Server
上周初步对Blazor WebAssembly进行了初步的探索(ASP.NET Core Blazor 初探之 Blazor WebAssembly).这次来看看Blazor Server该怎么玩. ...
- ASP.NET Core Blazor Webassembly 之 组件
关于组件 现在前端几大轮子全面组件化.组件让我们可以对常用的功能进行封装,以便复用.组件这东西对于搞.NET的同学其实并不陌生,以前ASP.NET WebForm的用户控件其实也是一种组件.它封装ht ...
- ASP.NET Core Blazor Webassembly 之 路由
web最精妙的设计就是通过url把多个页面串联起来,并且可以互相跳转.我们开发系统的时候总是需要使用路由来实现页面间的跳转.传统的web开发主要是使用a标签或者是服务端redirect来跳转.那今天来 ...
- 初探领域驱动设计(2)Repository在DDD中的应用
概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...
- CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探
CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...
- 从273二手车的M站点初探js模块化编程
前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数 ...
随机推荐
- C# 去除\0
在做项目的时候遇到了这种情况,如图 这个字符串包含了好多的\0,等你放大查看的时候又什么都不显示,十分惹人烦,哈哈 网上有的解决办法说 tmpStr.TrimEnd("\0");但 ...
- 封装PDO函数
funPDO.php <?php /** * @title: 封装PDO函数 * * @Features: * 1. 封装 SELECT ,INSERT,DELETE,UPDATE 操作 @do ...
- CTSC2017总结
这个博客已经弃坑近一年了,自从去年国赛大力卡线进队后这近一年来我的情况从博客一年没更就可见一斑,OI水平原(zhi)地(xian)踏(fu)步(chong),炉石和双升的姿势水平倒是提高不少. 在经历 ...
- VMware Workstation安装Red hat7.0联网问题总结
1.在red hat7当中iconfig命令是被取消了的,开发者用ip addr命令取代了ifconfig命令. 当然也是可以用ifconfig命令的 (前提是你安装的linux是可以联网的): 1) ...
- RSP小组——团队冲刺博客一——(领航)
RSP小组--团队冲刺博客一--领航 冲刺日期:2018年12月10日 团队目标 经过团队讨论,我们最新确定的α版本所需实现内容如下: 1.实现游戏代码的实现 2.在Android Studio上实现 ...
- vue项目使用webpack构建的本地服务环境,在手机上访问调试
使用vue脚手架构建的项目,一般在本地localhost运行,配合浏览器的模拟调试工具开发. 如果想看真机环境,又不想build到线上. webpack能配置电脑本地内网环境指向公网访问的! 1.打开 ...
- vuex学习
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 简单的理解就是你在state中定义了一个数 ...
- Python3.6 连接MySQL(二)转载
安装mysqlclient库 错误:OSError: mysql_config not found 解决: 方案一 ln -s /usr/local/mysql/bin/mysql_config / ...
- 1、了解计算机与操作系统发展阶段 2、选择一个具体的操作系统,结合计算机与操作系统的发展阶段,详细了解其渊源、发展过程、趋势,整理成简洁美观的图文博客发布。 Windows Mac os x Unix Linux Android 等。
1.了解计算机与操作系统发展阶段 操作系统并不是与计算机硬件一起诞生的,它是在人们使用计算机的过程中,为了满足两大需求:提高资源利用率.增强计算机系统性能,伴随着计算机技术本身及其应用的日益发展,而逐 ...
- 使用SSM重新开发计科院网站
一.游览 在游览器地址栏输入:http://localhost:8080/index,即访问计科院首页,由于前期对数据库以及JavaBean的设计考虑不够充分,导致后期的代码臃肿,所以项目启动时对首页 ...