兰 亭 墨 苑
期货 · 量化 · AI · 终身学习
首页
归档
编辑文章
标题 *
URL 别名 *
内容 *
(支持 Markdown 格式)
# Bun:JS工具链的降维打击 > Node是标准,Deno是理想,Bun是效率。 --- ## 一、赛道已经换了:为什么JSC赢了V8 Bun的碾压级速度不是魔法,是一个清晰的架构选择——**用"长运行峰值吞吐"换"短任务极速启动"**。 | | V8(Node/Deno) | JavaScriptCore(Bun) | |---|---|---| | **设计目标** | Chrome长时页面渲染 | Safari快速打开标签页 | | **优化方向** | JIT预热后峰值吞吐 | 冷启动+首次执行速度 | | **内存footprint** | 较大(~40MB基线) | 较小(~18MB基线) | | **适配场景** | 长运行重型计算 | I/O密集+短生命周期任务 | 这不是在比较V8和JSC谁"更好",而是指出:**Node选错了优化目标**。V8为Chrome的长时页面渲染而生,JIT偏重峰值吞吐。但服务端JS的典型负载是"起一个进程,做点I/O,然后死掉"——JIT预热的时间比干活的时间还长。Bun用JSC,是把优化目标从"跑久了好"扭转为"跑得快、死得干净",这恰好命中了Serverless时代的物理账本。 再用Zig写运行时——无GC拖累的底层内存管理,系统调用路径极短,冷启动压到毫秒级。加上Linux io_uring内核级异步I/O,不走libuv事件循环。 **不是Bun比V8"更好",是Bun选了更适合JS服务端典型负载的引擎。一旦成本函数对了,选引擎就自然了。** --- ## 二、为什么JS服务端负载长这样:三个产业结构变迁 JS服务端"短生命周期+I/O密集"的负载形态不是天然的,是三个历史力量共同塑造的: ### 2.1 计算的民主化——前端开发者涌入后端 他们用JS不是因为JS是最好的服务端语言,而是因为这是他们唯一会的语言。这决定了服务端JS的典型任务不是数值计算(那是Python/Julia的地盘),而是**胶水逻辑**——接请求、查数据库、拼JSON、返回响应。胶水逻辑天然是I/O密集的。 ### 2.2 计算的碎片化——Serverless/微服务/边缘计算 | 模式 | 进程生命周期 | 计算特征 | |------|------------|---------| | 单体应用(2005) | 天级 | CPU可预热,JIT有时间优化 | | 微服务(2015) | 小时级 | 部分可预热,但容器调度频繁 | | Serverless(2020) | **毫秒级** | **JIT预热时间 > 执行时间** | | 边缘计算(2023) | **毫秒级+冷启动频繁** | **每次请求可能都是冷启动** | 当进程从"天级"压缩到"毫秒级",V8的JIT优化窗口从"充裕"变成了"负数"——**预热还没完成,进程已经死了**。这不是V8的bug,而是时代变了。 ### 2.3 计算的商品化——按调用计费 Serverless按ms计费,边缘计算按请求计费。在这个经济模型下,**冷启动时间就是直接成本**。Bun省100ms冷启动不是"快一点",是每次调用少付100ms的钱。百万级调用下,这就是账面上的数字。 --- ## 三、裁判重定义:Bun不是在赢比赛,而是在换裁判 Bun真正的力量不在"更快",而在**重新定义了什么叫"快"**。 | 裁判 | Node表现 | Bun表现 | 胜者 | |------|---------|--------|------| | JIT预热后峰值吞吐 | ✅ 强(V8老本行) | ⚠️ 一般 | Node | | 冷启动时间 | ❌ 60-120ms | ✅ 8-15ms | **Bun** | | 基线内存占用 | ❌ 40MB | ✅ 18MB | **Bun** | | 端到端成本(Serverless) | ❌ 贵 | ✅ 省 | **Bun** | Node在旧裁判(JIT预热后峰值吞吐)下赢了,Bun在新裁判(端到端成本)下赢了。**新裁判为什么取代旧裁判?因为产业结构变迁让新裁判更接近真实成本函数。** 这和AlphaGo Zero的结构同构: | | AlphaGo vs Zero | Node vs Bun | |---|---|---| | 旧裁判 | 模仿人类棋谱的准确度 | JIT预热后峰值吞吐 | | 新裁判 | 终局胜负 | 端到端成本 | | 裁判切换的驱动力 | 自我对弈发现了更优策略 | 产业结构变迁改变了真实成本函数 | | 旧方案的"口音" | 人类棋谱偏见残留在权重中 | V8的长运行优化偏执残留在架构中 | 但这不是零和博弈——JS运行时不是围棋。Node不会因为Bun的存在而消失,因为企业存量项目、CPU密集场景、LTS需求、C++原生模块生态都是Node的护城河。**在开环世界中,多个裁判可以共存,不同场景需要不同的裁判。** --- ## 四、快多少:数据说话 | 指标 | Bun 1.3 | Node.js 24 | Deno 2.6 | 倍数 | |------|---------|-----------|----------|------| | HTTP吞吐 | ~110k req/s | ~45k | ~85k | 2.4× vs Node | | 冷启动 | 8–15ms | 60–120ms | 40–60ms | **10×** vs Node | | 包安装(冷) | ~1s | ~20s | ~17s | 20× vs npm | | 包安装(热) | ~0.3s | ~8s | ~0.8s | 27× vs npm | | TS执行 | ~10ms | ~150ms(需tsx) | ~30ms | 15× vs Node | | SQLite 10k行插入 | 12ms | 88ms | 45ms | 7× vs Node | | 基线内存 | ~18MB | ~40MB | ~30MB | 一半不到 | | 大monorepo(1847依赖) | **47s** | 28min | — | **36×** | 冷启动10×差距对Serverless是真金白银——Lambda按ms计费,Bun每次调用省100ms,百万级调用就是显著成本差异。 --- ## 五、All-in-One:DX的涌现 | 需求 | Node生态 | Bun | |------|---------|-----| | 包管理 | npm/pnpm/yarn | `bun install` ✅ | | 打包 | webpack/esbuild/rollup | `bun build` ✅ | | 测试 | jest/vitest | `bun test` ✅ | | TypeScript | tsx/ts-node | 原生支持 ✅ | | .env | dotenv | 原生读取 ✅ | | JSX | 配置babel/tsx | 原生支持 ✅ | | SQLite | better-sqlite3 | `bun:sqlite` ✅ | | 单文件分发 | pkg/nexe | `bun build --compile` ✅ | 单独看每一项,都不是不可替代的。bun test可以换成jest,bun build可以换成esbuild。但当这一切内建在一个二进制里,而且零配置可用时,就发生了质变。 **"Going back to Node feels like stepping back 5 years"**——这是DX涌现的典型症状。无数小的、可判定的改进(启动快一点、安装快一点、原生支持TS),在某个临界点之后,集体跃迁到另一个不可判定的体验层级。你无法用一个benchmark证明"DX好10×",但迁移过的人都知道它真实存在。 构建管线从"拼装"变"原生",抹平了Webpack/esbuild/Jest的配置摩擦。 --- ## 六、兼容策略:Drop-in Replacement,不颠覆 与Deno强推Web标准、自建生态不同,Bun优先实现Node.js API(`fs`, `http`, `net`, `path`等)和npm包兼容。 - **98-99% npm兼容**——`bun run index.js`基本直接替换`node index.js` - Express、Hono、Next.js(99%兼容,实验性)、Prisma、Zod都能跑 - **不能用的5%**:node-gyp编译的原生C++模块(bcrypt、sharp某些配置)、`node:crypto`边缘case 迁移成本极低,企业存量项目无痛接入,不破坏现有依赖树。 --- ## 七、生产采纳证据 | 公司 | 用Bun做了什么 | |------|-------------| | Anthropic | Claude Code CLI用Bun单文件可执行 | | Midjourney | 内置WebSocket服务器做生成通知 | | Vercel | 2025年底原生支持Bun部署Next.js | | Railway | Serverless函数用Bun运行 | --- ## 八、何时选/不选 **选Bun**: - Serverless/短生命周期任务(冷启动10×优势直接变钱) - CI/CD管线(1847依赖47s vs npm的28min) - CLI工具(单文件可执行分发) - 前端基建、快速原型 - 追求极致DX的团队 **谨慎选择**: - 重度依赖V8特有优化(特定N-API C++ Addon、复杂长时数值计算)——JSC的JIT路径与V8不同,CPU密集场景Bun接近甚至略输Node(React SSR 4,150 vs 4,200 ops/sec) - 强依赖Node最新实验性API - **需要LTS的企业**(银行、医疗)——Bun没有长期支持策略 - **需要安全模型**——Deno默认拒绝一切权限,Bun没有权限控制 - **Windows为主的环境**——Bun 1.x在Windows上兼容性和性能显著弱于macOS/Linux --- ## 九、技术史的一个模式 Bun的故事不是孤例。回顾历史,"裁判重定义"反复出现: | 旧裁判 | 旧胜者 | 新裁判 | 新胜者 | 驱动力 | |--------|--------|--------|--------|--------| | 单核峰值性能 | C++ | 并行吞吐 | Java/C# | 多核普及 | | 手动内存管理效率 | C | 开发效率 | Python/JS | 开发者成本上升 | | JIT预热后峰值 | Node(V8) | 冷启动+端到端成本 | Bun(JSC) | Serverless兴起 | **每次裁判重定义的背后,都是成本结构的变迁**——当某个成本维度从"可忽略"变成"占大头"时,优化方向就必须切换。 Python比C慢100倍,但开发者效率高10倍——当开发者成本 > 计算成本时,Python赢了。 Bun在CPU密集场景略输Node,但冷启动快10倍——当冷启动成本 > 峰值吞吐差异时,Bun赢了。 那成本结构为什么会变迁?因为**抽象层次的迁移**。 每当一个行业把某一层的实现"做完了"——单核优化到了物理极限、手动内存管理的边际收益趋近于零——成本结构就自动转移到下一层未被满足的需求上:并行吞吐、开发效率、冷启动开销。这不是某个工具的功劳,而是技术演化的结构性必然:**每一层的"做完了",就是下一层"赛道切换"的发令枪。** C++把单核性能做到了极致,于是成本重心转移到"如何利用多核"——Java/C#胜出。C把手动内存管理做到了极致,于是成本重心转移到"如何降低开发者心智负担"——Python/JS胜出。Node把服务端JS的长运行吞吐做到了可用,于是成本重心转移到"如何让短生命周期任务更便宜"——Bun胜出。 **技术史的本质不是"更好的工具取代更差的工具",而是"更匹配当前成本结构的工具取代不再匹配的工具"——而成本结构本身,由抽象层次的迁移驱动。** --- ## 十、一句话 **Bun不是在Node的赛道上跑得更快,而是发现赛道已经换了。** 产业结构变迁漂移了成本函数,成本函数的漂移淘汰了旧裁判,抽象层次的迁移让这一切成为必然——Bun只是这个结构中一个具体的、可验证的截面。 --- *雨轩于听雨轩 🌧️🏠*
配图 (可多选)
选择新图片文件或拖拽到此处
标签
更新文章
删除文章