守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 1764|回复: 2

[WebAssembly] WebAssembly 初尝

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52691
    钢镚
    1422

    开源英雄守望者

    发表于 2016-8-18 16:55:59 | 显示全部楼层 |阅读模式
    来源:http://www.zcfy.cc/article/build-your-first-thing-with-webassembly-culture-of-development-1031.html



    头一次听说 WebAssembly 的时候就觉得很酷,然后就超兴奋地开始尝试。但从一开始尝试的过程就不顺利,越来越让人灰心。本文的目的就是解决问题,让你免受困扰。

    beware of cliff

    读者须知

    本文写作于 2016 年 6 月 24 日。WebAssembly 是一项很新的、不稳定的技术;随着其标准化过程发展,本文中的任何内容都可能是错误的。

    不过先不管了....

    WebAssembly 是什么

    好吧,官网是这么描述的:

    WebAssembly,或者称作 wasm,是一项适用于 Web 编译的可移植的、体积与加载高效的格式。(WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web.)

    嗯...什么鬼?什么格式?文本(Text)?二进制(Binary)?老实说,这个描述真糟糕。所以不管它,收起那些 binggo 游戏卡(buzzword bingo cards,一种填词游戏,这些词通常都是流行语,阅读https://en.wikipedia.org/wiki/Buzzword_bingo了解更多 —— 译者注),根据我所有的经验来描述吧:

    WebAssembly/wasm 是用来编写高性能的、浏览器无关的 Web 组件的一种字节码规范。(WebAssembly or wasm is a bytecode specification for writing performant, browser agnostic web components.)

    有此妙语,听起来超棒,但仍然没 get 到点,接下来重点来了。WebAssembly 通过静态类型变量实现性能提升,运行时静态类型变量引用比动态类型变量更有效率。WebAssembly 由 W3C Community Group 制定,最终将被所有规范兼容的浏览器支持。还有杀手锏,最终我们可以使用任何语言编写这些 Web 组件(web components)。

    听起来酷了很多,不是么?

    一起开始吧

    学习新东西的时候,我通常会找尽可能最简单的例子来看它是如何工作的。不幸的是,对 WebAssembly 来说,这不太现实。在当前阶段,wasm 仅仅只是字节码规范。想象回到 1996 年,假如太阳公司(Sun Microsystems)的一些工程师们带来了 JVM,但却...没有 Java....若果真如此,我想当时的对话可能是这样的:

    —— “伙计们,快来看看我们做的这个执行字节码的虚拟机!” —— “真棒!但我们给它怎么写代码?”

    HelloWorld.class

    图:字节码形式的 HelloWorld

    —— “嗯..这问题提得好。等会儿我查查看。” —— “真棒,如果遇到了任何问题,告诉我们你的想法,在我们的 github page 上贴出来。” —— “你说对啦。我们现在先去看看其他项目。”

    这个例子有些糟糕,因为 JVM 是基于 Java 语言的;尽管如此,希望你还是 get 到点了。如果都没有将代码编译为字节码的工具,要起步就很困难了。那我们要怎么开始?

    WebAssembly 之前有什么

    多数技术都是创新的结果,特别是当合理的尝试成为正式规范时。wasm 也不例外,它实际上是 asm.js 的工作的延续, asm.js 是一个编写 javascript 组件的的规范,可编译为静态类型。wasm 的规范拓展了这些创意,它接受任何语言编译而成的字节码,这些字节码作为二进制文件而非文本文件通过网络传输;规范由很多来自主流浏览器厂商的代表们一起制定,而非仅仅是 Mozilla。

    asm.js 仅仅是一个使用 javascript 语言特征的最小子集编写 javascript 的规范。你可以手写一些简单的 asm.js 代码,如果你想弄脏你的手,这正是极好的方式。(等会儿最好将这放在单独的文件中,通常约定文件名格式为 your-module-name.asm.js。))

    function MyMathModule(global) {
        "use asm";
        var exp = global.Math.exp;
        function doubleExp(value) {
            value = +value;
            return +(+exp(+value) * 2.0);
        }
        return { doubleExp: doubleExp };
    }

    这还不是一个特别有用的函数,但符合规范。如果你觉得这很二,别人也是这么觉得的,不过基本上每一个字符都是必须的。在这当中,一元运算符 + 的作用是类型注解,这样编译器会知道那些变量是 double 类型的,运行时就不必再次分辨它们是什么。它相当挑剔,如果你把什么地方弄得一团糟,火狐控制台会给你一些合理的错误信息。

    如果你想在浏览器中使用,像下面这样:

    var myMath = new MyMathModule(window);
    for(var i = 0; i < 5; i++) {
        console.log(myMath.doubleExp(i));
    }

    一切正常的话,结果大概像下图这样:

    asm.js success

    开始尝试 WebAssembly

    现在我们已经有了一个可以工作的 asm.js 代码片段,可以使用 WebAssembly github page 提供的工具将其编译为 wasm。自己克隆代码仓库构建工具吧。这最麻烦了。这些工具一直在不断发展,代码会时不时挂掉,特别是在 Windows 环境下。

    不管你是用 Windows 还是 Mac,电脑上必须要安装 make 和 cmake 命令行工具。如果你在使用 Windows,你还需要安装 Visual Studio 2015。Mac 用户按照这里的说明 操作;Windows 用户按照这个说明操作。

    building binaryen

    图: Windows 下的工具构建

    对 WebAssembly 团队来说,发布可以工作的二进制文件意味着朝着正确的方向前进了一大步。

    构建成功之后,binaryen 目录下会有一个 bin 文件夹,其中有一些用来将 asm.js 转换为 wasm 的工具。第一个工具是asm2wasm.exe。它将 asm.js 代码转换为 .s 格式的代码,这些代码是生成 wasm 所需的抽象语法树(AST)的文本表现形式。运行工具,最终会得到类似下面的东西:

    (module
      (memory 256 256)
      (export "memory" memory)
      (type $FUNCSIG$dd (func (param f64) (result f64)))
      (import $exp "global.Math" "exp" (param f64) (result f64))
      (export "doubleExp" $doubleExp)
      (func $doubleExp (param $0 f64) (result f64)
        (f64.mul
          (call_import $exp
            (get_local $0)
          )
          (f64.const 2)
        )
      )
    )

    以后我们可以逐行分析上面的代码,但现在我只想让你看下它的样子。我还得提醒你一点,因为 wasm 是二进制格式的,所以像你今天对 javascript 所做的那样右击、查看源码是行不通的。从头到尾都是二进制码。目前的计划是查看 wasm 模块源码时对二进制格式进行反汇编,让人能读懂。

    接下来要做的是使用 wasm-as.exe 将 .s 格式的代码转换为 wasm 二进制码。运行文件,最后就能得到浏览器需要的真正的 wasm 二进制码。

    building wasm from asm.js

    图:将 asm.js 转换为 wasm 二进制码

    wasm bytecode

    图:wasm 二进制码

    紧接着,安装最新版的 Firefox 或 Chrome Canary,并启用 WebAssembly。

    如果你使用的是 Firefox,在地址栏中输入 about:config,点击“确认我会保证小心”。然后在搜索框中输入 wasm,双击javascript.options.wasm 将值设置为 true,然后重启浏览器。

    如果你使用的是 Chrome Canary,打开 chrome://flags,往下翻,找到 Experimental WebAssembly,点击“启用”链接,再重启浏览器。

    最后一步就是让模块在浏览器中跑起来。初次尝试时,这又是一大痛点,完全不知道怎么做。在规范中使用 wasm 模块的 API 一点都没找到。最后我在 Canary 的控制台上输入 WebAsse,并没有任何提示。接着输入 Was 的时候,提示出来了!控制台上打印出的对象大概最简陋的文档了,不过这时候我突然想到,可以用一些其他工具 (emscripten) 将代码编译为 wasm。不过这是另外一篇博客的话题了。

    一段时间之后,鼠标落在了 WebAssembly 的设计文档仓库上。我看到了一个名为 JS.md 的文件,点击之后,有一个 API 的说明。仔细看顶部斜体的文字。但最精彩的部分还是最底部的代码片段,演示了如何最低限度地加载模块。我所需要做的就是拆出相关部分进行尝试。

    fetch("my-math-module.wasm")
        .then(function(response) {
            return response.arrayBuffer();
        })
        .then(function(buffer) {
            var dependencies = {
                "global": {},
                "env": {}
            };
            dependencies["global.Math"] = window.Math;
            var moduleBufferView = new Uint8Array(buffer);
            var myMathModule = Wasm.instantiateModule(moduleBufferView, dependencies);
            console.log(myMathModule.exports.doubleExp);
            for(var i = 0; i < 5; i++) {
                console.log(myMathModule.exports.doubleExp(i));
            }
        });

    把代码放到 html 文件中,启动本地文件服务器,在浏览器中加载页面。下面是在浏览器中的结果:

    wasm in a browser

    浏览器中运行的 wasm (至少尝试运行了)

    我估计需要去提交一个 bug 报告了。记着,一切都是实验性的、不稳定的,所以当此类事情发生的时候,别灰心丧气。

    keep calm and file bug reports

    恭喜你

    你已经完成了第一个 WebAssembly 组件。接下来做些什么?目前我们碰到的还只是皮毛而已。在本例中手写 asm.js 很重要,但需要时间和耐心。使用 emscripten 将应用转换为 asm.js 要简单多了。关于这一点,我强烈建议你阅读 asm.js 规范,特别是内存模型的部分,因为其中的许多概念都被迁移到 WebAssembly 上了。另外一个怪异的事情是,目前还不能直接将数组作为函数参数。人们已经达成共识,这需要改变,但规范中尚未有关于这一点的。去看看指针逻辑吧。

    还有一点,在 wasm 中做一些工作的时候,你可能发展实际上 WebAssembly 还没普通的 javascript 运行得快。记住,现代的 javascript 引擎已经是高度优化的,wasm 要赶上这速度还需要时间。WebAssembly 还尚未进入准备生产的阶段。

    如果你有任何关于 wasm 或者本文中提到的工具的问题,在 Stack Overflow 中提出来,记得标上恰当的 tag。

    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    2016-8-19 16:08
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    4

    主题

    31

    帖子

    2628

    积分

    少尉

    Rank: 6Rank: 6

    威望
    0
    贡献
    8
    金币
    320
    钢镚
    25
    发表于 2016-8-18 17:21:02 | 显示全部楼层
    不错,学习了
    我是一个兵
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2016-8-19 16:03
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    1

    主题

    4

    帖子

    4259

    积分

    中尉

    Rank: 7Rank: 7Rank: 7

    威望
    0
    贡献
    16
    金币
    117
    钢镚
    10
    发表于 2016-8-18 17:37:35 | 显示全部楼层
    学习一下........
    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2024-4-19 04:08 , Processed in 0.058103 second(s), 30 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表