Wasmtime是由 bytecodealliance 开源的WebAssembly和WASI的小型高效运行时。它在Web内部运行WebAssembly代码,既能够用作命令行实用程序,也能够用作更大应用程序中嵌入的库。
具备以下特点:
轻量级
。Wasmtime是WebAssembly的独立运行时,可依据您的需要进行扩大。它适宜于微型芯片,也能够应用大型服务器。 Wasmtime也能够嵌入简直所有应用程序中。快
。Wasmtime建设在优化的Cranelift代码生成器上,可在运行时疾速生成高质量的机器代码。可配置
。无论您是须要提前预编译wasm,应用Lightbeam疾速生成代码还是在运行时进行解释,Wasmtime都能满足您执行wasm的所有需要。WASI
。Wasmtime反对一组丰盛的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
执行。