本文要点
Deno和Node.js都在基于C/C++的运行时上执行JavaScript代码,以实现较高的性能。
Deno是单一的二进制应用,不兼容NPM模块,并且很难将原生模块加入应用中。
WebAssembly提供了一种在Deno应用中运行高性能代码的途径。
对于服务端应用程序来说,WebAssembly是安全、可移植和轻量级的容器。
Rust编译器工具链为WebAssembly提供了强大的支持。
备受期待的Deno项目终于发布了1.0版本!Deno 是由 Node.js 的创始人 Ryan Dahl 创建的,旨在解决他所说的“我为Node.js感到遗憾的十件事”。
Deno 抛弃了 NPM 和臭名昭著的 node_modules。它是单个二进制可执行文件,可运行以 TypeScript 和 JavaScript 编写的应用程序。
但是,尽管 TypeScript 和 JavaScript 适合大多数 Web 应用程序,但它们可能难以满足计算密集型任务的需求,如神经网络训练和推理、机器学习和加密应用等。实际上,Node.js 就经常需要使用原生库来执行这些任务(例如使用 openssl 执行加密任务)。
既然没有类似 NPM 的系统来加入原生模块的话,我们该怎样在 Deno 上编写需要原生性能的服务端应用程序呢?这就要轮到 WebAssembly 上场了!在这篇文章中,我们将在 Rust 中编写一些高性能函数,并将它们编译为 WebAssembly,然后在你的 Deno 应用程序中运行它们。
太长不看版
从 GitHub 克隆或 fork这个Deno入门项目模板。按照说明操作,只需 5 分钟你就能在 Deno 中运行第一个 WebAssembly 函数(由 Rust 编写)。
一点背景
Node.js 之所以非常成功,是因为它为开发人员做到了鱼与熊掌兼得:JavaScript 的易用性(尤其是编写基于事件的异步应用程序时)以及 C/C++的高性能。Node.js 应用程序是用 JavaScript 编写的,但会在基于 C/C++的原生运行时上执行,这些运行时包括谷歌 V8 JavaScript 引擎和许多原生库模块。Deno 希望能复制这种成功路径,但在这个过程中它使用了 TypeScript 和 Rust 支持的现代技术栈。
Deno是用于JavaScript和TypeScript的简单、现代化且安全的运行时,它使用了V8引擎,并在Rust内构建。——deno.land网站。
在他的著名演讲“我为 Node.js 感到遗憾的十件事”中,Node.js 的创建者 Ryan Dahl 解释了从头开始创建 Deno 这个 Node.js 的竞争对手(甚至替代者)的理由。Dahl 的遗憾主要集中在 Node.js 管理第三方代码和模块的机制上。
用于将C模块链接到Node.js的复杂构建系统。
package.json、node_modules、index.js和其他NPM工件引入了不必要的复杂性。
于是,Deno 在管理依赖项时有意选择了一些方式来避免上述问题。
Deno是单个二进制可执行文件。
应用程序是使用TypeScript或JavaScript编写的,在代码中将依赖项明确声明为import语句,并带有完整的URL,链接到依赖项的源代码。
Deno与Node.js模块不兼容。
这些都没问题,但那些需要更高性能的应用程序该怎么办呢?例如需要在毫秒级别执行复杂神经网络模型运算的 AI 即服务应用程序?在 Deno 和 Node.js 中,许多函数都是通过 TypeScript 或 JavaScript API 调用,但以 Rust 或 C 语言编写的原生代码执行。在 Node.js 中,开发人员总是可以选择从 JavaScript API 调用第三方原生库。但我们目前无法在 Deno 中这样做吗?
Deno 中的 WebAssembly 支持
WebAssembly 是一种轻量级虚拟机,旨在以接近原生的速度执行可移植字节码。你可以将 Rust 或 C/C++函数编译为 WebAssembly 字节码,然后从 TypeScript 访问这些函数。对于某些任务,它可能比用 TypeScript 编写的等效函数要快得多。例如,这份IBM研究发现,对于某些数据处理算法,Rust 和 WebAssembly 可以将 Node.js 的执行速度提高 1200%至 1500%。
Deno 内部使用谷歌 V8 引擎。V8 不仅是一个 JavaScript 运行时,还是一个 WebAssembly 虚拟机。Deno 对 WebAssembly 提供了开箱即用的支持。Deno 为你的 TypeScript 应用程序提供了一个 API,以调用 WebAssembly 中的函数。
实际上,WebAssembly 中已经实现了一些流行的 Deno 组件。例如,Deno 中的sqlite module是使用 Emscripten 将 sqlite 的 C 源代码编译到 WebAssembly 中的成果。Deno WASI组件使 WebAssembly 应用程序可以访问操作系统的底层资源,例如文件系统。在本文中,我将教你如何用 Rust 和 WebAssembly 编写高性能的 Deno 应用程序。
设置
当然,第一步是安装Deno!在大多数系统上,这一步只需一条命令足矣。
由于我们正在用 Rust 编写函数,因此你还需要安装Rust语言编译器和工具。
最后,ssvmup工具可以自动执行构建过程并生成所有工件,以使你的 Deno 应用程序轻松调用 Rust 函数。同样,用一条命令就能安装 ssvmup 依赖项。
注意:ssvmup 使用 wasm-bindgen 在 JavaScript 和 Rust 源代码之间自动生成“胶水”代码,以便它们可以使用自己的原生数据类型来通信。没有它,函数参数和返回值只能限制在 WebAssembly 原生支持的一些非常简单的类型上(如 32 位整数)。例如,如果没有 ssvmup 和 wasm-bindgen,你就无法使用字符串或数组。
Hello world
首先,我们来研究一下 Deno hello world 示例中使用的 hello world 示例。你可以从 GitHub 获取hello world源代码和应用程序模板。
Rust 函数位于src/lib.rs文件中,只需在输入字符串前加上“hello”即可。注意,say()函数使用 #[wasm_bindgen]注解,使 ssvmup 可以生成必要的“管道”,以从 TypeScript 来调用它。
Deno 应用程序位于deno/server.ts文件中。这个应用程序从 pkg/functions_lib.js 文件(由 ssvmup 工具生成)中导入 Rustsay()函数。functions_lib.js 这个文件名是由Cargo.toml文件中定义的 Rust 项目名称确定的。
现在我们运行 ssvmup,将 Rust 函数构建为一个 Deno WebAssembly 函数。
ssvmup 成功完成任务后,你可以检查 pkg/functions_lib.js 文件,看看 Deno WebAssembly API 是怎样执行已编译的 WebAssembly 文件 pkg/functions_lib.wasm 的。
接下来运行 Deno 应用程序。Deno 需要读取文件系统的权限(因为它需要加载 WebAssembly 文件),并需要访问网络(因为它需要接收和响应 HTTP 请求)。
注意:如果你之前已经安装了 Deno,并在这里遇到了一个错误,这很可能是由于缓存过的库的版本冲突导致的。按照这里的指导来重建 Deno 缓存。
在另一个终端窗口中,你现在可以访问 Deno Web 应用程序,让它通过 HTTP 连接说 hello 了!
一个更复杂的例子
入门模板项目包括了几个更详细的示例,以展示如何在 Deno TypeScript 和 Rust 函数之间传递复杂的数据。下面是 src/lib.rs 中的其他一些 Rust 函数。请注意,它们每个都用 #[wasm_bindgen]注解过了。
也许最有趣的是 create_line()函数。它接收两个 JSON 字符串(每个字符串代表一个 Point 结构),并返回一个代表 Line 结构的 JSON 字符串。注意,Point 和 Line 结构都使用 Serialize 和 Deserialize 注解,这样 Rust 编译器就能自动生成必要的代码,以支持它们与 JSON 字符串之间的转换。
接下来我们检查一下 JavaScript 程序deno/test.ts,它显示了如何调用 Rust 函数。如你所见,String 和 &str 是 JavaScript 的简单字符串,i32 是数字,而 Vec 或 &[8]是 JavaScript Uint8Array。JavaScript 对象需要先通过 JSON.stringify()或 JSON.parse()才能传入 Rust 函数或从 Rust 函数返回。
运行 ssvmup 构建 Rust 库之后,在 Deno 运行时中运行 deno/test.ts 会生成以下输出:
下一步计划
现在我们就可以创建 Rust 函数,并从 Deno TypeScript 应用程序访问它们。你可以在 Rust 函数中放置大量计算密集型任务,并通过 Deno 提供高性能和安全的 Web 服务。这类服务的例子包括机器学习和图像识别等。
将来,你还可以通过WebAssembly系统接口(WASI),在你的 Deno 应用程序中访问随机数、环境变量和文件系统等系统资源。
作者介绍
Michael Yuan 博士是五本软件工程书籍的作者。他的最新著作《构建区块链应用》由 Addison-Wesley 在 2019 年 12 月出版。Yuan 博士是Second State的联合创始人,这是一家将 WebAssembly 和 Rust 技术引入云、区块链和 AI 应用程序的初创公司。Second State 使开发人员能够在 Node.js 上部署快速、安全、可移植和无服务器的 Rust 函数。感兴趣的读者可以订阅WebAssembly.Today通讯来获取最新信息。
原文链接:
评论 4 条评论