本文共 2064
字,阅读需要 5
分钟。
- 文章全部来自手打,不添加任何
AI
辅料。如果你没了解过bun
,没看过bun
官网,也没关系,看完文章就可以明白它所追求的目标。 - 我在了解、使用和思考
bun
的过程中,产生的见解和观点。
背景
最近看到 bun
的新博客,眼前一亮,如下图:
看到这个,我脑子一热,输出了一句卧槽,居然把空闲内存降低了 10~30%
。
我点进去一看,好家伙,Next.js idle memory usage
降低了 28%
!
从上图看,换句话说,相当于我服务器内存比之前节省 28%
,这省钱效果眼前一亮。举个例子。
线上环境:nextjs
使用 k8s
部署,线上 5
个 pod
- 优化前:每个
pod
1000M
内存 - 优化后:每个
pod
只需要720M
5
个 pod
相当于节省了 1400M
,非常客观。这对于 k8s
来说,内存的节省可以直接转化为可用配额,这是赤裸裸的给公司省钱啊。
遂想写一篇文章,谈谈我对 bun
的一些想法。
这里抛出我的观点:相比于 deno
,我更看好 bun
,看完下文,即可了解我看好的理由。
bun 是什么
整体概括为以下几句话:
第一句:bun
是性能更强、架构更现代化的 JS runtime
,或者说是更好的 nodejs
第二句:bun
从诞生之日起就在第一句的基础上,不懈努力的实现 nodejs
生态的 100%
兼容
第三句:bun
一直在努力实现 JS
生态的 all in one
第一句解读——满分的性能和架构
bun
是用 zig
语言实现,zig
是一门媲美 C
的编程语言,大家对 rust
都有所了解,可以这样去理解 zig
:
zig
和rust
在性能上不分伯仲- 编程界有很多接受不了
rust
语法的人,都拥抱了zig
所以想要实现性能更强的 js runtime
,那你的底层语言就要足够强。至此,deno
选择了 rust
,而 bun
选择了 zig
第二句解读——100%兼容nodejs
bun
的使命之一是实现 nodejs
生态的 100%
兼容,从 deno
走过的弯路看,bun
的使命是正确的,虽然难度大,但是有志者,事竟成,只要方向对,一直做这件事。总有 100%
兼容的那一天。
当我看到 bun
从诞生之时就在做这件事情,我就感觉 bun
值得期待,bun
的团队值得 nodejs
生态信任。
第三句解读——JS all in one
完全兼容 nodejs
生态,是 bun
展现给 JS
生态的诚意,而努力实现 JS
生态的 all in one
则是更好的造福整个 JS
生态。
怎么理解 all in one
,之前 antfu
分享 eslint
配置时,也提到了 all in one
,下图所示:
我们就用 antfu
对 all in one
的解释来理解 bun
的 js all in one
。
即:化繁为简,一统江湖。
与其把核心包,工具包交给社区生态,担心未来会面临的潜在问题,nodejs
就是 "前车之鉴" 。不如 由 bun
官方一统江湖。
官方喊话:Develop, test, run, and bundle JavaScript & TypeScript projects—all with Bun
翻译版:嘿~我的前端好兄弟,写 js
,ts
项目,用 Bun
就对了。我提供一条龙服务,什么包管理器、单测、构建等,全都有,而且借助 zig
,性能拉满,你眼还没眨完,我包安装好了,什么,单测也跑完了?
翻译版是我翻的,纯乐呵,主要是表达 bun
的 all in one
策略。除了内置包管理器、单测、构建。隐藏在官方喊话中的还有如下:
- 内置
websocket
实现,还带pub/sub
功能 - 内置 主流数据库
driver
:SQLite driver
、PostgresSQL driver
- 二进制打包,不依赖宿主环境,更易部署(
go
的爽感) jsx
、ts
直接支持(deno
也支持,老二和老三打架,ts-node
遭殃😂)monorepo
支持(pnpm workspace
那一套)- and so on...
bun
的 all in one
和 go
语言挺像,核心就是基建相关的,bun
团队负责做,当然社区也可以搞,官方也会继续做,原则上就是 Bun
团队会提供一个基于 Bun
的 all in one
的开发环境。并且会随着 bun
的迭代,不断增强。这带给我们的收益是:
- 不担心这些核心库,工具被投毒、挖矿等
- 降低使用的心智负担
- 更大范围受益
bun
团队的技术能力 - 给生态树立规范和榜样,起到带头作用
我很赞同 bun
的 all in one
策略,而且以现在时间点看,bun
官方在 all in one
策略上已经硕果累累了。
举例介绍
下文会选几个经典场景,介绍下 bun
。
qps 之王
相同环境下起 3000
端口,执行 oha http://localhost:3000 -n 500000 -H "Accept-Encoding: identity"
效果对比如下图:
node
deno
bun
从图中可以得出,bun:deno:node = 4:1.7:1
,性能可谓最强
只考虑 qps
情况下,bun
是 node
的 4
倍,理论上可以节省 75%
的服务器资源。从公司角度看,这是实实在在的省钱。
当然,理论不代表实际情况,还需要结合 tps
去分析。
内置跨平台 shell
这个用着是很爽,代码如下:
import { $ } from 'bun';
// window linux mac 都是一样语法
await $`echo "Hello, world!"`;
const response = await fetch("https://baidu.com");
const data = await $`gzip < ${response}`.arrayBuffer();
console.log('gzip data:', data)
执行 bun run index.ts
,效果如下:
快速的依赖安装
无全局缓存,从 0
开始安装依赖,bun
、pnpm
、yarn
耗费时间对比图:
可以看到, yarn
用了 49
秒, bun
在 13
秒, pnpm
在 11
秒
有全局缓存,无 node\_modules
。bun、pnpm、yarn
耗费时间对比图:
可以看到,有全局缓存的情况下,都挺快的,但是
bun
是最快的。
这里有个疑问,bun官网宣传的对比速度如下:
提到是通过 Installing dependencies from cache
。但是我实际测试没有怎么夸张,bun
的速度并没有很突出。
强大的单测
单测速度拉满,执行如下命令
git clone git@github.com:colinhacks/zod.git
cd zod
bun install
hyperfine --warmup 3 --runs 3 \ "bun test src" \ "npx vitest --config configs/vitest.config.ts" \ "npx jest -c configs/babel-jest.config.json" \ "npx jest -c configs/ts-jest.config.json" \ "npx jest -c configs/swc-jest.config.json"
单测性能对比如下图:
可以看到 bun
内置的 test
在 100ms
以内就完成单测运行了,简直离谱。
该有的功能都有,而且很快
贴个官方文档图,就不在介绍了:
令人愉悦的 --hot
自带 hot reload
,如下 gif
图演示:
all in one
的使用体验就是安心和舒服。
bun 彩蛋部分
月提交 commit 248次
写了一个脚本对 bun
仓库的 commit
进行了分析,如下图所示:
从 2021年4月
第一次 commit
开始,到现在,平均每月提交 248
次,迭代速度拉满。
脚本就是用 bun
写的,而且用的 bun
内置的跨平台 shell
工具 $
,涉及代码如下:
import { $ } from "bun";
async function getMonthlyCommits(repoPath: string) {
const result = await $`git log --format="%aI"`.text();
}
这内置跨平台 shell
,用起来太爽了。
go、rust、zig的qps表现
测了下 go
、 rust
和 zig
。
go:17万
rust:17万
zig: 7万
测完,有点奇怪,为什么 zig
的 qps
比 rust
和 go
差这么多,下图是开源的一个测评:
上图是在 linux
服务器上测的,我是在 mac
电脑上测的。估计和底层实现有关,我能想到的就是一个是没有对 mac系统
做优化,另一个是还需要调整某些参数。
这里没有细究。如果说 bun
是 7
万,我能接受,但是 zig
也是 7
万,那就挺奇怪的。
思考
我们用惯了某某语言,某某技术后,对于新势力可能会变的迟钝,会觉得不成熟,不稳定,没必要。但是换个角度思考,我们用惯的这些,在没成熟,不稳定时,也有很多人会觉得没必要,我们要用包容和期待的技术视野去关注、了解和分析新语言、新技术、新风向的发展,这样你更容易成为第一批吃螃蟹的人。