LLRT:AWS 为 Serverless 造的低延迟 JavaScript 运行时
阅读时间: 大约 10 分钟
LLRT:AWS 为 Serverless 造的低延迟 JavaScript 运行时

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 里有几个具体机制:
- AWS SDK v3 原生内嵌:把常用的
@aws-sdk客户端编进可执行文件,并用原生实现替换掉 SDK 里的 Hash 计算、XML 解析等 JS 依赖。按打包体积分三档:no-sdk(不含 SDK)、std-sdk(常用客户端)、full-sdk(全部客户端)。 - TLS 连接预热:
LLRT_SDK_CONNECTION_WARMUP=1(默认开启)在函数 init 阶段并行建立 TLS 连接,官方称这”显著降低冷启动”。 - GC 阈值可调:默认
LLRT_GC_THRESHOLD_MB=20,内存到 20MB 才触发 GC。 - 强制打包:官方要求依赖按
browser平台打包、tree-shaking,TypeScript 必须在部署前转成 ES2023——运行期绝不做转译,因为那会消耗本可避免的 CPU 与内存。
四、关键数据:官方基准的真实分位
官方基准的工况是 DynamoDB Put、ARM 架构、128MB 内存。从官方发布的 LLRT 基准图(上图)可读出如下毫秒级分位值:
| 指标 | p50 | p90 | p99 | p100 |
|---|---|---|---|---|
| 冷启动 λ(总耗时) | 64.16ms | 72.62ms | 83.17ms | 85.61ms |
| 冷启动 HTTP(往返) | 235.61ms | 253.87ms | 285.32ms | 304.57ms |
| 热启动 λ(总耗时) | 14.94ms | 31.50ms | 35.79ms | 236.86ms |
| 热启动 HTTP(往返) | 43.72ms | 60.48ms | 68.61ms | 272.19ms |
其中冷启动样本 64/64、热启动样本 20000/20000,成功率均为 100%。对照的 Node.js 20 基准图如下:

五、评测方法批判:为什么它测的是”往返”而不是官方 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 的关键,几乎都来自官方自述:
- 它是实验性项目:README 顶部用 WARNING 明确 “LLRT is an experimental package … intended only for evaluation purposes”,不建议直接上生产关键链路。
- 不是 Node.js 平替:兼容性矩阵里大量
node:模块只是部分支持(⚠️)或干脆不支持(✘)——cluster、dgram、http2、inspector、vm、worker_threads、node:sqlite、node:test等均不支持,http/https还是”计划中的部分支持”。 - CPU 密集任务反而更慢:官方在 Limitations 里明说,在大数据处理、蒙特卡洛模拟、几十万上百万次循环这类任务上,没有 JIT 的 LLRT 明显跑不过 JIT 运行时。它最适合的是数据转换、实时处理、AWS 服务集成、鉴权校验这类短小函数。
- “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。