LLRT:AWS 为 Serverless 造的低延迟 JavaScript 运行时

AWS
Lambda
JavaScript
Serverless
开源
运行时
2026/10/2
·

阅读时间: 大约 10 分钟

LLRT:AWS 为 Serverless 造的低延迟 JavaScript 运行时

LLRT 官方 DynamoDB Put 冷/热启动分位延迟(ARM、128MB 内存),单位毫秒

Serverless 函数的本质是”短命”:实例起来、跑一次、销毁。Node.js、Bun、Deno 这类运行时为通用场景设计,都带一个 JIT 编译器——它在长跑里是优势,但在”只活几十毫秒就结束”的 Lambda 里,JIT 的启动与内存开销反而成了纯负担。AWS Labs 为此开源了 LLRT(Low Latency Runtime):一个用 Rust 编写、以 QuickJS 为 JS 引擎、刻意不带 JIT 的轻量运行时,官方称在 AWS Lambda 上可带来超过 10 倍的启动加速与最高 2 倍的整体成本下降。本文基于其官方 README 与基准图,拆解它的真实数字与边界。

一、背景:为什么 AWS 要再造一个 JS 运行时

README 里的 “Rationale” 一节讲得很直白:Node.js、Bun、Deno 都是优秀的运行时,但它们面向通用应用,依赖 JIT 在运行中动态编译优化代码。JIT 带来两块固定成本——一是它本身极其复杂、撑大了运行时体积;二是它需要持续消耗 CPU 与内存做热点识别与编译。在短生命周期的 Serverless 实例里,这些投入收不回来。LLRT 的取舍就是:不要 JIT,把省下的 CPU/内存全部还给业务代码,换更快的启动。

二、是什么:QuickJS + Rust 的无 JIT 运行时

  • JS 引擎:QuickJS(而非 V8),天然体积小、启动快;
  • 宿主语言:Rust,原生模块与 AWS SDK 用 Rust 重写,减少 JS 层依赖;
  • 目标平台:AWS Lambda,支持自定义 runtime、Lambda Layer、容器镜像、SAM、CDK 等多种接入方式;
  • 语言标准:支持 ES2023,但官方反复强调 “NOT a drop-in replacement for Node.js”,也明确”永远不会是”。

三、技术机制:原生 SDK + 预热连接 + 无 JIT

LLRT 提速不只是换引擎,README 里有几个具体机制:

  1. AWS SDK v3 原生内嵌:把常用的 @aws-sdk 客户端编进可执行文件,并用原生实现替换掉 SDK 里的 Hash 计算、XML 解析等 JS 依赖。按打包体积分三档:no-sdk(不含 SDK)、std-sdk(常用客户端)、full-sdk(全部客户端)。
  2. TLS 连接预热:LLRT_SDK_CONNECTION_WARMUP=1(默认开启)在函数 init 阶段并行建立 TLS 连接,官方称这”显著降低冷启动”。
  3. GC 阈值可调:默认 LLRT_GC_THRESHOLD_MB=20,内存到 20MB 才触发 GC。
  4. 强制打包:官方要求依赖按 browser 平台打包、tree-shaking,TypeScript 必须在部署前转成 ES2023——运行期绝不做转译,因为那会消耗本可避免的 CPU 与内存。

四、关键数据:官方基准的真实分位

官方基准的工况是 DynamoDB Put、ARM 架构、128MB 内存。从官方发布的 LLRT 基准图(上图)可读出如下毫秒级分位值:

指标p50p90p99p100
冷启动 λ(总耗时)64.16ms72.62ms83.17ms85.61ms
冷启动 HTTP(往返)235.61ms253.87ms285.32ms304.57ms
热启动 λ(总耗时)14.94ms31.50ms35.79ms236.86ms
热启动 HTTP(往返)43.72ms60.48ms68.61ms272.19ms

其中冷启动样本 64/64、热启动样本 20000/20000,成功率均为 100%。对照的 Node.js 20 基准图如下:

Node.js 20 在同一 DynamoDB Put、ARM、128MB 工况下的冷/热启动分位

五、评测方法批判:为什么它测的是”往返”而不是官方 Init Duration

这是 LLRT 基准最值得注意的方法论细节。AWS Lambda 控制台通常用 Init Duration 衡量冷启动,但官方在 README 里专门解释了为什么不用它:

  • Lambda 文档对 Init Duration 的定义是”runtime 加载函数并执行 handler 之外代码所花的时间”,它不包含把代码拷贝进 Lambda 沙箱的时间;
  • 而用户真实感知的冷启动延迟,恰恰要把代码拷贝算进去。

所以 LLRT 改测 round-trip request duration(请求往返耗时):图中标 λ 的那一行 = Init Duration + Function Duration 的合计,HTTP 那一行则是端到端往返。这个口径选择更贴近用户体验,但也意味着——它和你在 Lambda 控制台里看到的 Init Duration 数字不能直接对比,迁移时要自己按同样口径重测。此外,基准只有”DynamoDB Put + 128MB ARM”这一种工况,“10 倍启动加速、2 倍成本下降”是该工况下的上限宣传值(“up to”),并非所有函数都能拿到。

六、口径偏差与官方自承认的局限

这一节是理解 LLRT 的关键,几乎都来自官方自述:

  1. 它是实验性项目:README 顶部用 WARNING 明确 “LLRT is an experimental package … intended only for evaluation purposes”,不建议直接上生产关键链路。
  2. 不是 Node.js 平替:兼容性矩阵里大量 node: 模块只是部分支持(⚠️)或干脆不支持(✘)——cluster、dgram、http2、inspector、vm、worker_threads、node:sqlite、node:test 等均不支持,http/https 还是”计划中的部分支持”。
  3. CPU 密集任务反而更慢:官方在 Limitations 里明说,在大数据处理、蒙特卡洛模拟、几十万上百万次循环这类任务上,没有 JIT 的 LLRT 明显跑不过 JIT 运行时。它最适合的是数据转换、实时处理、AWS 服务集成、鉴权校验这类短小函数。
  4. “10x/2x”是上限不是均值:原文是 “up to over 10x” 与 “up to 2x”,取决于函数是否命中它原生优化的路径。

七、适用与不适用场景

适合:

  • 跑在 AWS Lambda 上、逻辑短小、主要做 API 网关后的鉴权/校验/数据转换、频繁调 AWS 服务的函数;
  • 冷启动延迟敏感、且愿意接受实验性运行时换取毫秒级启动与更低账单的团队。

不适合:

  • CPU 密集、长循环、大数据批处理函数(无 JIT 会吃亏);
  • 重度依赖未兼容 Node API(worker_threads、vm、完整 http2 等)的现有代码;
  • 希望”改个 runtime 配置就无痛迁移”的团队——它要求你按 browser 平台重新打包并改写部分依赖。

八、客观分析与谁该关注

优势:无 JIT 的取舍换来了 Lambda 上极短的冷启动(官方工况冷启动 λ p50 仅约 64ms)、原生内嵌 SDK、连接预热、Apache 2.0 开源、支持 SAM/CDK 主流 IaC。局限:实验性质、Node 兼容性残缺、CPU 密集场景倒退、“10x/2x”为单工况上限宣传。如果你是重度 AWS Lambda 用户且函数多为短小的事件驱动逻辑,LLRT 值得做一次 A/B 压测;但它的定位是”补充”而非”替代”——官方自己都说,重度场景仍应留在 Node.js。

参考来源