文章摘要
Bun 的安装速度显著快于 npm、pnpm 和 yarn,尤其是在大型代码库中,安装时间从分钟级缩短至毫秒级。Bun 将包安装视为系统编程问题,通过减少系统调用、缓存二进制清单、优化压缩包提取、利用操作系统原生文件复制和多核 CPU 扩展等技术实现高效安装。文章回顾了 2009 年技术环境的局限性,强调了 Bun 在现代硬件和网络条件下的性能优势。
文章总结
Bun Install 背后的技术揭秘
bun install 的速度非常快,平均比 npm 快 7 倍,比 pnpm 快 4 倍,比 yarn 快 17 倍。特别是在大型代码库中,这种速度差异尤为明显。过去需要几分钟的操作,现在只需几毫秒。
Bun 之所以如此快,是因为它将包安装视为系统编程问题,而不是 JavaScript 问题。Bun 通过减少系统调用、将清单缓存为二进制文件、优化 tarball 解压、利用操作系统原生文件复制以及跨 CPU 核心扩展等方式,显著提升了安装速度。
硬件演进与系统调用的瓶颈
在 2009 年,Node.js 刚刚发布,当时的硬件条件与今天大不相同。如今,NVMe 硬盘的速度已达到 7000 MB/s,比 Node.js 设计时的硬盘速度快了 70 倍。然而,当前的包管理器仍然在优化十年前的问题。2025 年,真正的瓶颈不再是 I/O,而是系统调用。
每次程序需要操作系统执行某些操作(如读取文件、打开网络连接、分配内存)时,都会进行系统调用。每次系统调用,CPU 都需要进行模式切换,从用户模式切换到内核模式,再切换回来。这种模式切换的开销非常大,每次切换需要 1000-1500 个 CPU 周期,相当于 500 纳秒。对于现代 SSD 来说,这种开销是巨大的。
Bun 的优化策略
Bun 通过最小化系统调用和利用操作系统特定的优化来提升安装速度。Bun 使用 Zig 语言编写,直接调用系统调用,避免了 JavaScript 引擎、线程池、事件循环等中间层的开销。例如,Bun 读取文件时,直接调用 openat() 系统调用,内核立即执行并返回数据,没有任何额外的运行时开销。
异步 DNS 解析与二进制清单缓存
Bun 在解析 package.json 时,会预取 DNS 查询,使得网络解析在依赖分析完成之前就开始。此外,Bun 将包清单缓存为二进制文件,避免了每次安装时重复解析 JSON 的开销。这种二进制格式的缓存使得 Bun 在访问包信息时,只需进行简单的指针运算,无需分配内存或解析对象。
优化 tarball 解压与文件复制
Bun 在解压 tarball 时,会先将整个压缩文件下载到内存中,然后根据 gzip 文件的最后 4 字节预分配内存,避免了重复的缓冲区调整和复制操作。在文件复制方面,Bun 根据操作系统和文件系统的不同,选择最有效的复制策略。例如,在 macOS 上,Bun 使用 clonefile() 系统调用,通过写时复制技术高效复制整个目录树。
多核并行与无锁数据结构
Bun 利用现代 CPU 的多核优势,采用无锁的工作窃取线程池架构,最大化并行化 I/O 密集型任务。每个线程都有自己的内存池,避免了线程间的内存分配竞争。Bun 的网络操作也独立运行,使用 64 个并发 HTTP 连接,确保网络下载和 CPU 处理互不阻塞。
结论
Bun 的设计并不是革命性的,但它确实针对当前的硬件条件进行了优化。当 SSD 每秒可以处理百万次操作时,为什么还要接受线程池的开销?当文件系统支持写时复制时,为什么还要复制千兆字节的数据?Bun 展示了如何通过重新思考现有工具的可能性,来定义下一个十年的开发者生产力。
Bun 的快速安装并不是“魔法”,而是为当前硬件条件量身定制的工具所带来的结果。
评论总结
Bun的积极体验
- 评论1:用户首次使用Bun,对其内置服务器和SQLite表示赞赏,认为无需依赖其他工具,非常适合开发。
引用:- "The built-in server and SQLite meant i didn’t need any dependencies besides bun itself."
- "I do almost all of my development in vanilla js despite loathing the node ecosystem."
- 评论1:用户首次使用Bun,对其内置服务器和SQLite表示赞赏,认为无需依赖其他工具,非常适合开发。
Bun与其他语言的工具对比
- 评论2:用户对比了Python的uv和JS的Bun,询问Ruby和PHP是否有类似的工具,并质疑这些语言的开发者是否对当前的依赖管理器速度满意。
引用:- "Python has uv, JS has bun, what does Ruby or PHP have?"
- "Are the devs using those languages happy with how fast the current popular dependency managers are?"
- 评论2:用户对比了Python的uv和JS的Bun,询问Ruby和PHP是否有类似的工具,并质疑这些语言的开发者是否对当前的依赖管理器速度满意。
Bun的普及度问题
- 评论3:用户对Bun的普及度感到惊讶,指出在GitHub上,npm和pnpm的使用率远高于Bun,并猜测可能是因为Bun作为运行时的兼容性问题。
引用:- "npm is 35 times more popular and pnpm is 11 time more popular than bun."
- "Is it because it is a runtime, and getting compatibility there is harder than just for a straight package manager?"
- 评论3:用户对Bun的普及度感到惊讶,指出在GitHub上,npm和pnpm的使用率远高于Bun,并猜测可能是因为Bun作为运行时的兼容性问题。
Bun与Node.js的技术对比
- 评论4:用户指出Bun使用Zig语言编写,直接访问系统调用,而Node.js使用libuv进行异步I/O管理,认为Node.js本可以采用类似技术。
引用:- "Bun is written in Zig, a programming language that compiles to native code with direct system call access."
- "No one forced npm to be using this abstraction, and npm probably should have been a nodejs addon in C/C++ in the first place."
- 评论4:用户指出Bun使用Zig语言编写,直接访问系统调用,而Node.js使用libuv进行异步I/O管理,认为Node.js本可以采用类似技术。
Bun在特定环境下的兼容性问题
- 评论5:用户在使用Bun时遇到与WSL1的兼容性问题,导致安装失败。
引用:- "I had a hard time getting it to play nicely with WSL1 on Windows 10."
- "error: An unknown error occurred (Unexpected)"
- 评论5:用户在使用Bun时遇到与WSL1的兼容性问题,导致安装失败。
Bun的性能与基准测试问题
- 评论7:用户指出Bun的基准测试中缺少npm(缓存)的数据,并认为总结统计数据可能有误。
引用:- "I think they forgot to include the benchmark time for 'npm (cached)'."
- "I think the summary statistics are also incorrect."
- 评论7:用户指出Bun的基准测试中缺少npm(缓存)的数据,并认为总结统计数据可能有误。
Bun与其他工具(如Deno)的对比
- 评论8:用户对Deno的表现感到好奇,并建议使用Vite模板项目作为基准测试。
引用:- "I'm somewhat curious how Deno stands up with this."
- "I'd probably start a vite template project for react+ts+mui as a baseline."
- 评论8:用户对Deno的表现感到好奇,并建议使用Vite模板项目作为基准测试。
Bun的安装时间优化是否关键
- 评论9:用户认为依赖安装时间的优化并不是项目的关键问题,相比人力和基础设施成本,节省的时间微不足道。
引用:- "the time it takes to install node modules is not a critical blocker for any project."
- "Cutting 20 seconds off the dependency install time is just not a make or break issue."
- 评论9:用户认为依赖安装时间的优化并不是项目的关键问题,相比人力和基础设施成本,节省的时间微不足道。