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 devhttps://github.com/cranestation/wasmtime/releases/download/dev/wasmtime-dev-x86_64-linux.tar.xz######################################################################## 100.0%    Creating directory layout  Extracting Wasmtime binarieswasmtime-dev-x86_64-linux/wasmtime-dev-x86_64-linux/wasmtimewasmtime-dev-x86_64-linux/LICENSEwasmtime-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:

# wasmtimewasmtime 0.19.0Wasmtime WebAssembly RuntimeUSAGE:    wasmtime <SUBCOMMAND>FLAGS:    -h, --help       Prints help information    -V, --version    Prints version informationSUBCOMMANDS:    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 fileIf a subcommand is not provided, the `run` subcommand will be used.Usage examples:Running a WebAssembly module with a start function:  wasmtime example.wasmPassing command line arguments to a WebAssembly module:  wasmtime example.wasm arg1 arg2 arg3Invoking 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 mainimport (    "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.goHello 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 mainimport (    "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.gogcd(6, 27) = 3

结语

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