乐趣区

关于webassembly:WebAssembly运行时Wasmtime

Wasmtime 是由 bytecodealliance 开源的 WebAssembly 和 WASI 的小型高效运行时。它在 Web 内部运行 WebAssembly 代码,既能够用作命令行实用程序,也能够用作更大应用程序中嵌入的库。

具备以下特点:

  • 轻量级 。Wasmtime 是 WebAssembly 的独立运行时,可依据您的需要进行扩大。它适宜于微型芯片,也能够应用大型服务器。Wasmtime 也能够嵌入简直所有应用程序中。
  • 。Wasmtime 建设在优化的 Cranelift 代码生成器上,可在运行时疾速生成高质量的机器代码。
  • 可配置 。无论您是须要提前预编译 wasm,应用 Lightbeam 疾速生成代码还是在运行时进行解释,Wasmtime 都能满足您执行 wasm 的所有需要。
  • WASIWasmtime 反对一组丰盛的 API,用于通过 WASI 规范与主机环境进行交互。
  • 规范 。Wasmtime 通过了官网的 WebAssembly 测试套件,实现了 wasm 的官网 C API,并且还实现了 WebAssembly 的 proposals。Wasmtime 开发人员也始终与 WebAssembly 规范流程密切相关。

目前反对语言:

  • Rust – the ["https://crates.io/crates/wasmtime">wasmtime crate](https://zhuanlan.zhihu.com/p/224862650/%3C/code)
  • C – the f="https://bytecodealliance.github.io/wasmtime/c-api/">wasm.h, wasi.h, and wasmtime.h headers
  • Python – the ["https://pypi.org/project/wasmtime/">wasmtime PyPI package](https://zhuanlan.zhihu.com/p/224862650/%3C/code)
  • .NET – the ["https://www.nuget.org/packages/Wasmtime">Wasmtime NuGet package](https://zhuanlan.zhihu.com/p/224862650/%3C/code)
  • Go – the [wasmtime-go repository](https://zhuanlan.zhihu.com/p/224862650/ht%3C/code%3Etps://pkg.go.dev/github.com/bytecodealliance/wasmtime-go)

装置

在 macos 和 linux 上装置 Wasmtime CLI 非常简单,只需执行以下命令即可:

$ curl https://wasmtime.dev/install.sh -sSf | bash

Windows 或是其余操作系统用户,须要到 GitHub Releases 下载。
因为我的操作系统是 centos,所以可能展示的与您有所不同。我执行装置脚本之后,有如下输入:

curl https://wasmtime.dev/install.sh -sSf | bash
  Installing latest version of Wasmtime (dev)
    Checking for existing Wasmtime installation
    Fetching archive for Linux, version dev
https://github.com/cranestation/wasmtime/releases/download/dev/wasmtime-dev-x86_64-linux.tar.xz
######################################################################## 100.0%
    Creating directory layout
  Extracting Wasmtime binaries
wasmtime-dev-x86_64-linux/
wasmtime-dev-x86_64-linux/wasmtime
wasmtime-dev-x86_64-linux/LICENSE
wasmtime-dev-x86_64-linux/README.md
     Editing user profile (/root/.bashrc)
Warning: Your profile (/root/.bashrc) already mentions Wasmtime and has not been changed.
    Finished installation. Open a new terminal to start using Wasmtime!

而后咱们查看以下是否胜利装置了 wasmtime:

# wasmtime
wasmtime 0.19.0
Wasmtime WebAssembly Runtime
USAGE:
    wasmtime <SUBCOMMAND>
FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information
SUBCOMMANDS:
    config      Controls Wasmtime configuration settings
    help        Prints this message or the help of the given subcommand(s)
    run         Runs a WebAssembly module
    wasm2obj    Translates a WebAssembly module to native object file
    wast        Runs a WebAssembly test script file
If a subcommand is not provided, the `run` subcommand will be used.
Usage examples:
Running a WebAssembly module with a start function:
  wasmtime example.wasm
Passing command line arguments to a WebAssembly module:
  wasmtime example.wasm arg1 arg2 arg3
Invoking a specific function (e.g. `add`) in a WebAssembly module:
  wasmtime example.wasm --invoke add 1 2

装置结束,咱们接下来 Hello world 搞起。

Demo

Wasmtime 可作为 Go 模块应用。接下来介绍如何将 Wasmtime 增加到您的我的项目中,并提供一些示例阐明能够应用 WebAssembly 模块实现的操作。

确保您正在应用带有模块反对的 Go 1.12 或更高版本。
首先创立一个 go 模块我的项目:

$ mkdir hello-wasm
$ cd hello-wasm
$ go mod init hello-wasm

而后编写 main.go,具体代码如下:

package main
import (
    "fmt"
    "github.com/bytecodealliance/wasmtime-go"
)
func main() {engine := wasmtime.NewEngine()
    // Almost all operations in wasmtime require a contextual `store`
    // argument to share, so create that first
    store := wasmtime.NewStore(engine)
    // Compiling modules requires WebAssembly binary input, but the wasmtime
    // package also supports converting the WebAssembly text format to the
    // binary format.
    wasm, err := wasmtime.Wat2Wasm(`
      (module
        (import """hello" (func $hello))
        (func (export "run")
          (call $hello))
      )
    `)
    check(err)
    // Once we have our binary `wasm` we can compile that into a `*Module`
    // which represents compiled JIT code.
    module, err := wasmtime.NewModule(engine, wasm)
    check(err)
    // Our `hello.wat` file imports one item, so we create that function
    // here.
    item := wasmtime.WrapFunc(store, func() {fmt.Println("Hello from Go!")
    })
    // Next up we instantiate a module which is where we link in all our
    // imports. We've got one import so we pass that in here.
    instance, err := wasmtime.NewInstance(store, module, []*wasmtime.Extern{item.AsExtern()})
    check(err)
    // After we've instantiated we can lookup our `run` function and call
    // it.
    run := instance.GetExport("run").Func()
    _, err = run.Call()
    check(err)
}
func check(e error) {
    if e != nil {panic(e)
    }
}

最初运行:

$ go run main.go
Hello from Go!

当然当咱们 wasm 模块代码比拟宏大的时候,咱们能够将该代码放到一个以.wat 结尾的文件中。而后应用 NewModuleFromFile 函数,从指定 wat 文件中加载模块代码。
例如:
咱们创立以下 wasm 文本模块,次要导出用于计算两个数字的最大公分母的函数。命名为 gcd.wat。

(module
  (func $gcd (param i32 i32) (result i32)
    (local i32)
    block  ;; label = @1
      block  ;; label = @2
        local.get 0
        br_if 0 (;@2;)
        local.get 1
        local.set 2
        br 1 (;@1;)
      end
      loop  ;; label = @2
        local.get 1
        local.get 0
        local.tee 2
        i32.rem_u
        local.set 0
        local.get 2
        local.set 1
        local.get 0
        br_if 0 (;@2;)
      end
    end
    local.get 2
  )
  (export "gcd" (func $gcd))
)

而后批改咱们的 main.go 文件,如下:

package main
import (
    "fmt"
    "github.com/bytecodealliance/wasmtime-go"
)
func main() {engine := wasmtime.NewEngine()
    store := wasmtime.NewStore(engine)
    module, err := wasmtime.NewModuleFromFile(engine, "gcd.wat")
    check(err)
    instance, err := wasmtime.NewInstance(store, module, []*wasmtime.Extern{})
    check(err)
    gcd := instance.GetExport("gcd").Func()
    val, err := gcd.Call(6, 27)
    fmt.Printf("gcd(6, 27) = %dn", val.(int32))
    check(err)
}
func check(e error) {
    if e != nil {panic(e)
    }
} 

运行 main.go 有如下输入:

$ go run main.go
gcd(6, 27) = 3

结语

其实 wasm 对于 go 的反对并不是特地好。在当前的文章中,咱们应用 rust 语言创立一个 wasm 程序,而后间接应用诸如 wasmtime example.wasm 执行。

退出移动版