Socket.IO 服务器基准测试
I’m happy to help translate the article, but I need the full text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line, formatting, and code blocks unchanged while translating the rest into Simplified Chinese.
设置
竞争者
| Label | Runtime | WebSocket server |
|---|---|---|
| node‑ws | Node.js 24.11.1 | ws |
| node‑uws | Node.js 24.11.1 | uWebSockets.js v20.52.0 |
| bun‑ws | Bun 1.3.6 | ws |
| bun‑native | Bun 1.3.6 | @socket.io/bun-engine 0.1.0 |
ws 是默认的。它是纯 JS 且可靠,但 不快(剧透:它确实不快)。
测试服务器是我最近项目 Versus Type 后端的略作修改的版本——一个实时 PvP 打字游戏。我去掉了认证、速率限制和数据库调用。
对于负载生成器,我使用 Artillery 并配合 artillery-engine-socketio-v3 插件,以模拟数千个并发客户端通过 WebSocket 连接并进行游戏。
硬件
| 角色 | 实例 | 规格 |
|---|---|---|
| Server | AWS Standard B2als v2 | 2 vCPU, 4 GB RAM, Ubuntu 22.04 LTS |
| Attacker | AWS Standard B4als v2 | 4 vCPU, 8 GB RAM, Ubuntu 22.04 LTS |
攻击流程
- Artillery 每秒生成 4 个虚拟用户。
- 每个用户调用
/api/pvp/matchmake。 - 服务器运行匹配算法并返回 房间 ID(每个房间最多 6 名玩家)。
- 用户通过 WebSocket 连接,加入房间,并接收游戏状态(文本段落)。
- 服务器广播倒计时;玩家等待倒计时至 0。
- 用户以 60 WPM 的速度发送 按键事件(≈ 每 200 ms 一个事件)。
- 对于 每一次 按键,服务器验证输入、更新状态,并将新状态广播给房间内的所有人。
- 用户每秒发送一次 ping 事件,用于延迟追踪。
文本段落足够长,确保在基准测试结束前不会有游戏结束。(真实服务器还会每秒广播系统消息和 WPM 更新。)
GitHub 仓库:(包含服务器、客户端以及结果数据)。
Source: …
结果
综合冠军
Node + uWS(蓝线)在所有指标上均优于其他配置,唯一例外是内存使用量,此项由 Bun 领先。
0 – 800 客户端
- Bun 服务器的 事件循环延迟 显著更低(约 0 ms),远低于 Node 服务器。
node‑uws稳定性最佳。ws服务器(无论是 Bun 还是 Node)在 p95 延迟 上会爬升至 15‑20 ms。- 其余两种配置保持在 ≈ 5 ms,表现极其稳固。
800 – 1 500 客户端
node‑ws爆炸式增长——在约 1 k 客户端 时延迟急剧上升。bun‑ws与bun‑native也出现类似情况,只是稍晚一些。- 事件循环延迟呈现相同的趋势。
- CPU 在约 1 k 客户端 时对
node‑ws达到 100 %,bun‑ws在约 1.2 k,bun‑native在约 1.3 k。 node‑uws即使在 1.5 k 客户端时也保持在 ≈ 80 % CPU,并以类似速率上升。- 除
node‑uws外,吞吐量均出现不稳定。 - 内存方面:
node‑uws先出现异常下降后再回升;Bun 服务器整体使用 更少的内存——Bun 的内存管理令人印象深刻。
结论:node‑ws 无法承受负载,而 node‑uws 则保持平稳,延迟低且事件循环延迟小。
1 500 – 2 100 客户端
node‑ws、bun‑ws与bun‑native实际上已经 死亡——延迟飙升至天际。node‑uws仍然以恒定的 ≈ 80 % CPU 运行,且保持低延迟。- 注意:
node‑ws的 p95 延迟在一段时间内看似保持平稳(低于bun‑native),这是因为指标记录中断;Artillery 的 pushgateway 会在新数据到来前一直显示最后一次记录的值。
2 100 – 3 300 客户端
node‑uws继续 保持稳定——CPU 维持在 80 % 左右,延迟低,服务器响应迅速。- 其他所有配置都 不堪重负——CPU 达到 100 %,出现大幅延迟峰值,并频繁崩溃。
要点
| 配置 | 优势 | 劣势 |
|---|---|---|
| node‑uws | 综合性能最佳,延迟稳定,事件循环滞后低,能够在约 80 % CPU 使用率下处理 > 3 k 客户端。 | 内存使用略高于 Bun。 |
| bun‑native | 内存占用极低,在少量客户端时事件循环滞后也很低。 | 无法维持高客户端数量;在约 1.3 k 客户端后延迟急剧上升。 |
| bun‑ws | 早期事件循环滞后低,内存使用良好。 | 在负载下比 bun‑native 更早失效。 |
| node‑ws | 简单,默认选项。 | 在约 1 k 客户端时崩溃;CPU 与延迟均较高。 |
结论: 如果你的实时应用流量很大且追求原始性能,Node + uWebSockets.js 是显而易见的首选。若内存是主要考虑因素且你对 Bun 感到满意,Bun 的原生引擎是一个可靠的次选——但需留意其可扩展性上限。

`node-uws` is the only one still standing. It's at ~90‑100 % CPU now.
Throughput starts to become less stable, and latency slowly creeps up. It goes dead after ~3 250 clients.
We can say it could handle a solid 3 000‑3 100 concurrent clients just fine—more than double the next best (`bun-native`).
完整图表
CSV 文件可在此处的 GitHub 仓库获取。
Bun,发生了什么?
看到 bun-native 在这里被彻底击垮令人惊讶,因为 Bun 的 WebSocket 服务器底层使用的是 uWebSockets。
我并不完全清楚具体原因,但可能是因为 @socket.io/bun-engine 仍然非常新(v0.1.0),其中可能存在低效的实现和抽象层,导致额外的开销。




