zoukankan      html  css  js  c++  java
  • 初探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 
    ", 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实现的函数的运行性能对比。

    参考资料

  • 相关阅读:
    【unity3d游戏开发之基础篇】unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子
    【unity3d游戏开发之疑难杂症】Unity3d工程如何与MonoDevelop工具进行调试
    【unity3d游戏开发之疑难杂症】解决Unity3d脚本支持中文问题
    cocos2d 中添加显示文字的三种方式(CCLabelTTF 、CCLabelBMFont 和CCLabelAtlas)
    xcode连不上ipad的原因
    【unity3d游戏开发之疑难杂症】Error while importing package: Couldn't decompress package
    AS3 event flow 事件冒泡机制 以及 stopImmediatePropagation() stopPropagation()用法
    【unity3d游戏开发之基础篇】利用射线实现鼠标控制角色转向和移动(角色移动一)
    Asp.net Session认识加强Session究竟是如何存储你知道吗?
    Windows 7下VS2008无法调试2.0.50727.4952版本mscorlib.dll的解决办法
  • 原文地址:https://www.cnblogs.com/detectiveHLH/p/9881640.html
Copyright © 2011-2022 走看看