用 WasmEdge 在 WebAssembly 中运行 JavaScript

serverless 技术社区 2021-09-18 15:08:15

 

用 WasmEdge 在 WebAssembly 中运行 JavaScript

 

WebAssembly 最初是作为“浏览器中的 JavaScript 替代品”。其想法是在浏览器中安全地运行编译自 C/C++ 或 Rust 等语言的高性能应用程序。在浏览器中,WebAssembly 和 JavaScript 并列运行。

用 WasmEdge 在 WebAssembly 中运行 JavaScript

 

随着云中越来越多地使用 WebAssembly ,Wasm 现在是云原生应用程序的通用 runtime。与类似 Docker 的应用程序容器相比,WebAssembly runtime 以更低的资源消耗实现更高的性能。云中 WebAssembly 的常见用例包括以下内容

  • 用于 serverless 函数即服务 (FaaS) 的 runtime
  • 将用户定义的函数嵌入到 SaaS 应用或数据库
  • 用于 service mesh sidecar 应用的 runtime
  • 用于网络代理的可编程插件
  • 边缘设备的沙盒 runtime ,包括软件定义汽车和智能工厂

可是,在云原生应用场景中,开发者常常想要使用 JavaScript 来编写商业应用。这意味着现在我们必须在 WebAssembly 内支持JavaScript。此外,我们应该支持在 WebAssembly runtime 中从 JavaScript 调用 C/C++ 或 Rust 函数,充分利用 WebAssembly 的计算效率。 WasmEdge WebAssembly runtime 已经能够做到这一点。

 

用 WasmEdge 在 WebAssembly 中运行 JavaScript

云中的 WebAssembly 和 JavaScript

 

WasmEdge

WasmEdge 是一个领先的云原生 WebAssembly runtime,由 CNCF(云原生计算基金会) 托管 。它是当今市场上最快的 WebAssembly runtime。 WasmEdge 支持所有标准的 WebAssembly 扩展以及 Tensorflow 推理、networking、KV 存储和图像处理等专有扩展。其编译器工具链不仅支持 WebAssembly 语言,如 C/C++、Rust、Swift、Kotlin 和 AssemblyScript,还支持常规 JavaScript。

WasmEdge 应用可以嵌入到 C 程序、 Go 程序、 Rust 程序、 JavaScript 程序,或者操作系统的 CLI 中。WasmEdge 可以由以下工具管理:

  • Docker 工具(例如 CRI-O)
  • 编排工具 (例如 K8s)
  • Serverless 平台 (例如 Vercel、Netlify、 AWS Lambda、腾讯 SCF)
  • 数据流框架 (例如 YoMo 和 Zenoh)

现在,你可以在由 WasmEdge 支持的 serverless 函数、微服务和 AIoT 应用程序中运行 JavaScript 程序!WasmEdge 不仅可以运行普通的 JavaScript 程序,而且还允许开发者使用 Rust 和 C/C++ 在 WebAssembly 的安全沙箱中创建新的 JavaScript API。

在 WasmEdge 中构建 JavaScript 引擎

首先,让我们为 WasmEdge 构建一个基于 WebAssembly 的 JavaScript 解释器程序。这个程序基于 QuickJS ,并且带有 WasmEdge 扩展,例如 network sockets 和 Tensorflow 推理,并且作为 JavaScript API 被合并到解释器中。 首先,需要安装 Rust 来构建解释器。

如果你只想使用解释器来运行 JavaScript 项目,你可以跳过这个部分。确保你已经安装了 Rust和 WasmEdge。

Fork 或 clone wasmedge-quickjs Github repos 来开始。本文中所有的示例都会在 wasmedge-quickjs 里算。

$ git clone https://github.com/second-state/wasmedge-quickjs

按照 repo 中的说明,你就能够为 WasmEdge 构建 JavaScript 解释器。

$ `rustup target add wasm32-wasi`
$ cargo build --target wasm32-wasi --release

基于 WebAssembly 的 JavaScript 解释器程序位于被构建的 target 目录中。你现在可以尝试一个简单的 “hello world” JavaScript 程序 (example_js/hello.js),它会打印出命令行参数到控制器。

`args = args.slice(1)`
`print("Hello",…args)`

在 WasmEdge 的 QuickJS runtime 运行 hello.js 文件,如下。注意,命令行中的 --dir .:. 是要准许 wasmedge 读取文件系统中 hello.js文件的本地目录。

$ wasmedge --dir .:. target/wasm32-wasi/release/quickjs-rs-wasi.wasm example_js/hello.js WasmEdge Runtime
Hello WasmEdge Runtime

接下来,让我们尝试一些更高级的 JavaScript 程序。

JavaScript networking 示例

解释器支持 WasmEdge networking socket 扩展,以便 JavaScript 程序可以建立到互联网的 HTTP 连接。这是一个 JavaScript 示例。

let r = GET("http://18.235.124.214/get?a=123",{"a":"b","c":[1,2,3]})
print(r.status)
    
let headers = r.headers
print(JSON.stringify(headers))

let body = r.body;
let body_str = new Uint8Array(body)
print(String.fromCharCode.apply(null,body_str))

在 WasmEdge runtime 运行 JavaScript ,在 CLI 运行下面的命令。

$ wasmedge --dir .:. target/wasm32-wasi/release/quickjs-rs-wasi.wasm example_js/http_demo.js

你应该能在控制器中看到打印出的 HTTP GET 结果。

JavaScript Tensorflow 推理示例

解释器支持 WasmEdge Tensorflow lite 推理扩展,以便 JavaScript 可以运行 ImageNet 模型进行图像分类。 这是 JavaScript 的示例。

import {TensorflowLiteSession} from 'tensorflow_lite'
import {Image} from 'image'

let img = new Image('./example_js/tensorflow_lite_demo/food.jpg')
let img_rgb = img.to_rgb().resize(192,192)
let rgb_pix = img_rgb.pixels()

let session = new TensorflowLiteSession('./example_js/tensorflow_lite_demo/lite-model_aiy_vision_classifier_food_V1_1.tflite')
session.add_input('input',rgb_pix)
session.run()
let output = session.get_output('MobilenetV1/Predictions/Softmax');
let output_view = new Uint8Array(output)
let max = 0;
let max_idx = 0;
for (var i in output_view){
    let v = output_view[i]
    if(v>max){
        max = v;
        max_idx = i;
    }
}
print(max,max_idx)

在 WasmEdge runtime 运行 JavaScript ,你可以在 CLI 上执行以下操作,使用 Tensorflow 重新构建 QuickJS 引擎,然后使用 Tensorflow API 运行 JavaScript 程序。

$ cargo build --target wasm32-wasi --release --features=tensorflow
... ...
$ wasmedge-tensorflow-lite --dir .:. target/wasm32-wasi/release/quickjs-rs-wasi.wasm example_js/tensorflow_lite_demo/main.js
label:
Hot dog
confidence:
0.8941176470588236

注意:

  • --features=tensorflow 编译器标志使用 WasmEdge Tensorflow 扩展构建一个 QuickJS 引擎版本。
  • wasmedge-tensorflow-lite 程序是 WasmEdge 包的一部分。它是内置 Tensorflow 扩展的 WasmEdge runtime

现在应该可以看到 TensorFlow lite ImageNet 模型识别的食品名称。

--features=tensorflow编译器标志使用 WasmEdge Tensorflow 扩展构建 QuickJS 引擎的一个版本。 wasmedge-tensorflow-lite 程序是 WasmEdge 软件包的一部分。 它是内置 Tensorflow 扩展的 WasmEdge 运行时。

进一步加速

上面的 Tensorflow 推理示例需要 1-2 秒才能运行。这在 Web 应用场景中是可以接受的,但还能改进。回想一下,由于其 AOT(ahead of time)优化,WasmEdge 是当今最快的 WebAssembly Runtime。 WasmEdge 提供了一个 wasmedgec 实用程序来将 wasm文件编译为原生的 so 共享库。你可以使用 wasmedge 来运行 so 文件而不是 wasm 文件以获得更快的性能。

下面的例子使用了 wasmedge 和 wasmedgec 的扩展版本来支持 WasmEdge Tensorflow 扩展。

$ wasmedgec-tensorflow target/wasm32-wasi/release/quickjs-rs-wasi.wasm quickjs-rs-wasi.so
$ wasmedge-tensorflow-lite --dir .:. quickjs-rs-wasi.so example_js/tensorflow_lite_demo/main.js
label:
Hot dog
confidence:
0.8941176470588236

这次的图像分类任务可以在0.1秒内完成。这至少是 10 倍的改进!

so 共享库不能跨机器和操作系统移植。你应该在部署和运行应用程序的机器上运行 wasmedec 和 wasmedec-tensorflow。

关于 QuickJS 的注释

选择 QuickJS 作为我们的 JavaScript 引擎可能会引发性能问题。由于缺乏 JIT 支持,QuickJS 是不是比 v8 慢很多?没错!但是……

首先,QuickJS 比 v8 小很多。事实上,它只需要 v8 消耗的 runtime 资源的 1/40(或 2.5%)。你可以在单个物理机上运行比 v8 函数多得多的 QuickJS 函数。

其次,对于大多数业务逻辑应用程序,原始性能并不重要。应用程序可能具有计算密集型任务,例如动态 AI 推理。 WasmEdge 允许 QuickJS 应用程序使用高性能 WebAssembly 来完成这些任务,而在 v8 中添加此类扩展模块并不容易。

第三,众所周知,许多 JavaScript 安全问题源于 JIT。也许在云原生环境中关闭 JIT 并不是一个坏主意!

接下来呢?

这些示例演示了如何在 WasmEdge 中使用 quickjs-rs-wasi.wasm JavaScript 引擎。 除了使用 CLI,你还可以使用 Docker / Kubernetes 工具来启动 WebAssembly 应用程序或将应用程序嵌入到你自己的应用程序或框架中,正如我们在本文前面所讨论的那样。

在接下来的两篇文章中,我将专注讨论如何将 JavaScript 与 Rust 结合使用,充分利用好这两种语言。

  • 如何在 WasmEdge 中将简单的 JavaScript 片段合并到高性能 Rust 应用中。
  • 如何在 WasmEdge 中将高性能本机函数用作 JavaScript API。

云原生 WebAssembly 中的 JavaScript 仍然是下一代云和边缘计算基础设施中的新兴领域。我们才刚刚开始!如果你有兴趣,欢迎加入我们的 WasmEdge项目。你也可以通过提出 feature request issue 告诉我们你的需求)。

...全文
3133 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

217

社区成员

发帖
与我相关
我的任务
社区描述
Serverless 技术爱好者的聚集地
其他 企业社区
社区管理员
  • serverless 技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧