likes
comments
collection
share

又一个JavaScript运行时?LLRT 有点不一样(☁️云计算专用)

作者站长头像
站长
· 阅读数 4

前言

背景

在云服务,尤其是 serverless 的领域,成本和费用是非常关键的问题。对于开发者来说,费用是花了多少钱,对于云计算服务商自己,成本是提供相同的服务能力的前提下自己花费了多少计算资源(CPU,内存等)。那么,如果这个新的运行时可以降低内存占用,服务商用同样的机器资源就能服务更多的客户,收获更多的money💰,这就是技术带来的价值。

在 serverless 的领域,启动速度(startup time)也是一个关键问题。当用户调用服务时,你要启动资源,在用户不使用时,需要销毁资源。那假设用户每次call自己写的服务都要等待一大段时间启动,是不是更可能会有客户流失呢?这就是问题所在。

那么 LLRT 是如何解决这些问题的呢?

特性

LLRT 有以下特性,

  1. 基于 QuickJS 作为语言的引擎,在 QuickJS 上封装网络/文件读取等功能,相比于 V8 引擎,QuickJS 抛弃了 JIT 等复杂的特性,它有更精简的代码和更快的启动速度,同时支持的 JavaScript 特性也足够新(ES2020),这就带来了更快的启动速度。
  2. 基于 Rust 封装外层功能,众所周知,当你比较语言性能或执行速度时可能不太好说 Rust 是最快的语言,然而当你比较内存占用时,Rust在这方面的优势几乎是毫无争议的。基于 Rust 编写的 LLRT 拥有极低的内存占用,可以给厂商包括客户自己节省不少的资源耗费。在云计算时代,资源就 == 💰!

就这两点基本就总结了 LLRT 的不同之处,是不是特别好理解呢?下面我们再来看一看技术细节。

技术栈

QuickJS 是基于 C 的,Rust 来调用它需要做一层 binding,即使用 rquickjs,作为语言引擎,QuickJS 或者 rquickjs 是用来执行举行的 JavaScript 代码的,可以类比为解释器(Interpreter),在使用时需要把 JavaScript 代码作为文本传入,引擎会解释执行代码,并把结果返回,这样就完成了 JavaScript 代码的运行。

在外层,LLRT 通过封装一系列功能来提供 serverless 的服务,我们看看项目目录就能大概知道,

又一个JavaScript运行时?LLRT 有点不一样(☁️云计算专用)

通过 Rust 编写一系列网络/文件/加密等功能,就可以实现在云计算平台上与数据库或者储存服务交互,确实是安全且省内存。

案例

我们来看看官方仓库里提供的例子,

import DynamoDB from "aws-sdk/clients/dynamodb.js";

const client = new DynamoDB();

export const handler = async (event) => {
    await client
        .putItem({
            TableName: process.env.TABLE_NAME,
            Item: {
                id: {
                    S: Math.random().toString(36).substring(2),
                },
                content: {
                    S: JSON.stringify(event),
                },
            },
        })
        .promise();
    return {
        statusCode: 200,
        body: "OK",
    };
};

DynamoDB 是亚马逊的一个数据库服务,通过简单的把这段代码在 serverless 平台上交给 LLRT 执行,用户就能有一个读写储存的接口,这也是 serverless 代码的典型场景。

极少的计算逻辑和简短的代码,这也是为什么不需要用到 V8 那么复杂的引擎的原因,V8 是一个 JIT 的引擎,它能做到在运行时查看并优化热点代码,编译成原生语言以提高执行速度,然而在我们的场景里性能的瓶颈主要来源于网络/储存IO而不是代码逻辑的执行,所以一个精简的引擎还是很节省资源的。

参考