ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

谁才是最快的Web框架?六款主流框架实测对比与选型指南

2026/10/4 23:17:06 拓冰建站 浏览量
谁才是最快的Web框架?六款主流框架实测对比与选型指南 这两年聊性能几乎每个后端群里都会冒出同一个送命题Web框架到底谁最快不同人拿出不同榜单有人吹 Rust 系框架秒天秒地有人说 Node 才是实战之王Python 那边也不服气。与其继续打嘴仗不如自己搭一套环境跑一遍实测。所以这篇就是一份完整的 Web框架性能对比记录我把六款主流框架请上同一台机器跑三种典型业务场景记录吞吐量、延迟、CPU 和内存开销最后结合原理聊聊快和慢背后的真正原因。这篇内容不是让你照搬某一个跑分数字就完事而是把这套压测方法、参数设置、排查手段都交代清楚。后端开发、做技术选型的架构师、以及正在优化线上接口性能的人都可以从里面找到能直接上手的东西。测试数据有参考意义但更重要的是背后的分析逻辑为什么某个框架快为什么某个框架在特定场景下慢以及怎么用同样的方法测出适合你自己业务的那个“速度王者”。1. 对决之前先把测试环境和工具整明白性能测试最怕两件事测出来的数字不可复现或者对比的基数不一致。我见过很多团队拿笔记本跑 benchmark涡轮风扇一开数字暴涨 30%然后拿着这组数据去定框架选型这就很危险。所以在正式开跑之前先把环境、工具和流程统一起来。1.1 硬件与系统配置标准化这次测试选用两台配置完全一致的虚拟机8 核 vCPU、16 GB 内存、SSD 磁盘操作系统是 Ubuntu 22.04 LTS内核 5.15。网上很多 benchmark 会故意把机器配置写得模棱两可我这边强调一下两台机器一台专门跑被测框架一台专门跑压测工具避免压测工具和被测服务抢 CPU。系统层面有几个必须动手的优化项。第一把 CPU 调节器设为 performance 模式命令是cpupower frequency-set -g performance确保 CPU 不会因为负载低而自动降频也不会因为短时高负载而突然提频。第二关闭超线程或者直接把进程绑定到固定物理核用taskset -c 0-7限定被测进程使用哪几个核避免调度抖动。第三关闭防火墙并调整文件描述符限制ulimit -n 65535是最低要求否则高并发下连接数先爆掉。所有这些调整看起来都是“无关紧要的小事”但叠加起来对最终数据的影响非常大。测试的意义在于横向对比只要环境一致、方法一致哪怕绝对数字和别人的机器不同框架之间的相对差异仍然有很高的参考价值。1.2 压测工具选型wrk 为主hey 辅助压测工具我用的是 wrk搭配一套 lua 脚本用于自定义请求另外用 hey 做交叉验证。wrk 的优势是单机就能轻松打出高并发它基于 epoll线程模型非常高效。安装方式也很简单apt install wrk或者从 GitHub 拉源码编译几分钟搞定。wrk 的核心几个参数是-t线程数、-c连接数和-d压测时长。这次统一使用-t 8 -c 256 -d 60s即 8 个线程、256 个并发连接、持续 60 秒。这个组合能覆盖大多数 Web 服务的压力模型也不会因为并发数太大导致 wrk 自身成为瓶颈。实际压测时还有一个细节每次正式测试之前先跑 10 秒钟的预热请求。原因是 JVM 有 JIT 编译预热、Node 和 Python 也有模块加载和缓存填充过程直接上来就跑会让某些框架的成绩被严重低估。预热结束后休息 10 秒再正式跑 60 秒并记录数据。第 1.3 节会补全整个脚本逻辑。1.3 资源监控用 mpstat 和 pidstat 看真相只盯着 requests/s 远远不够。一个框架能跑到每秒十万请求但如果 CPU 已经打满、内存持续上涨、磁盘 IO 偶尔飙升那这个结果到了生产环境根本撑不住。所以我同时开了三组监控mpstat -P ALL 1 60看每个 CPU 核心的使用率pidstat -d 1 60看被测进程的磁盘读写free -m每秒记录一次内存变化。另一个容易忽略的指标是延迟分布。wrk 默认输出会给出 Latency 的平均值和标准差但我建议再跑一轮wrk --latency把 p50、p75、p99、p99.99 都记录下来。高并发场景下平均值漂亮没有任何意义尾延迟才是用户真实体验的写照。后面的数据解读部分会专门强调这一点。2. 参战选手六款主流框架的定位差异选框架不能只看跑分每款框架的设计哲学天差地别。这次参战的有 Node.js 20 上的 Fastify 4、Python 3.12 上的 FastAPI、Go 1.22 上的 Gin、Rust 1.75 上的 Actix-Web、Java 21 上的 Spring WebFlux以及 PHP 8.3 上的 Laravel 11 Octane。六位选手基本代表了后端领域的主流技术栈和编程模型。2.1 FastifyNode 生态里最“卷”的性能派Fastify 在 Node 生态里的定位非常清晰高吞吐、低开销、完全异步。它相比 Express 最大的改进是路由查找使用了类似基数树的算法并且内置了 fast-json-stringify 用于极速 JSON 序列化。测试时我把日志关掉logger: false同时把默认的trustProxy关掉只保留必要的路由和返回逻辑。Node 本身是事件循环模型单线程处理并发 I/O但这不意味着它只能用一个核。实际部署时我用pm2 start app.js -i 8起了 8 个进程每个进程绑定一个 CPU 核心。这也是生产环境比较常见的多进程部署方式。这里必须提醒一句Fastify 在写业务代码时千万不要用同步阻塞操作比如fs.readFileSync之类一旦出现整个事件循环都会被卡住跑分直接崩给你看。这个坑也是后面第 5.3 节要展开排查的一个典型案例。2.2 FastAPIPython 后台的异步门面FastAPI 的亮点在于 Pydantic v2 的序列化能力和原生 async 支持。Pydantic v2 底层核心是 Rust 写的所以它的序列化一小块比老版 Pydantic 快了好几倍。测试时我用 Uvicorn 作为服务器并用--workers 8开启 8 个 worker 进程。Python 的多 worker 要注意 GIL 的限制CPU 密集型代码即使开 8 个 worker也只能在多个进程间并行单个进程内无法真正并行执行 CPU 任务。不过 Web 请求大多是 I/O 密集数据库查询和网络读写的等待时间远大于 CPU 计算时间所以 async 多进程的组合仍然能吃满多核。FastAPI 测试的路由我用async def声明里面只做消息构造和 JSON 返回避免引入不必要的依赖。如果要模拟真实业务可以加一次 PostgreSQL 查询这个在第 3 节的数据库场景里会详细讲。2.3 GinGo 圈子里最稳的中坚力量Go 本身是编译型语言没有 JIT 预热过程冷启动性能就很硬。Gin 又做了极致的路由压缩和上下文对象池化内部复用gin.Context减少堆内存分配。我测试时设置了gin.SetMode(gin.ReleaseMode)并把默认的 Logger 中间件去掉因为日志中间件在高并发下会引入大量字符串格式化和写盘操作不适合做基准测试。Go 的服务部署非常省心编译出来就是一个静态二进制。测试时我用GOMAXPROCS8并搭配taskset -c 0-7绑定核心确保调度稳定。Gin 的中间件生态很丰富生产环境里常见的 CORS、鉴权、限流都能直接封装这些在压测“空路由”时感受不到但在真实业务里很有价值。2.4 Actix-WebRust 性能尖子生提到性能Rust 系框架不可能缺席。Actix-Web 4 基于 actor 模型内部是多线程执行器请求会被分发到多个 worker 上并行处理。空路由场景下 Actix-Web 的峰值吞吐量一直是 benchmark 榜单头部的常客。要让 Actix-Web 跑出最佳成绩Cargo 的 release profile 是关键。默认 release 模式只开了基本优化我会在Cargo.toml里加上[profile.release] lto fat、codegen-units 1、panic abort这些配置能显著提升最终二进制性能。另外Actix-Web 的workers数量默认是 CPU 逻辑核数压测前我会显式设为 8。Rust 的上手成本确实高但换来的是几乎没有运行时开销也没有 GC 停顿。在压测场景里它的表现很稳定CPU 占用曲线非常平滑这是很多带 GC 的语言做不到的。2.5 Spring WebFluxJVM 生态的响应式代表Spring WebFlux 走的是完全响应式、非阻塞的路子底层基于 Netty避免了传统 Servlet 模型里“一个请求一个线程”的资源浪费。Java 21 提供的虚拟线程也改变了并发模型的体验但 WebFlux 依然适合大量 I/O 等待的场景。JVM 系框架最大的考验是启动和预热时间。冷启动可能需要 3 到 5 秒压测前 20 秒的预热一定要做足否则 JIT 还没完成编译数据会很难看。我测试时用-Xms2g -Xmx2g固定堆内存避免运行时反复扩缩容造成抖动。Spring Boot 这种“全家桶”框架即使只加载 WebFlux 模块类路径依然很长这其实是它空路由场景的天然劣势。2.6 Laravel Octane让 PHP 摆脱“每次请求重新启动”的宿命PHP 传统 PHP-FPM 模式最大的开销在于请求结束后所有资源全部销毁下一次请求又得重新加载框架和业务代码。Octane 改变了这个模型进程常驻内存路由、配置、容器都可以跨请求复用性能直接上了一个台阶。测试时我用php artisan octane:start --serverroadrunner --workers8 --max-requests10000Worker 数量设为 8每个进程处理 10000 个请求后自动回收重建防止长期运行产生的内存碎片问题。PHP 的强项从来不是极限跑分而是开发效率和生态丰富度但 Octane 至少让它在性能榜单上保留了一席之地。3. 三轮压测从 hello world 到数据库查询环境备齐、框架就位接下来就是真刀真枪跑数据。三轮测试场景分别是空路由、JSON 序列化、模拟数据库查询覆盖从框架底子到真实业务链路的复杂度跃迁。每轮压测重复三次取中位数作为最终结果。3.1 第一轮空路由纯拼框架底子空路由场景就是访问/ping返回固定字符串pong不涉及序列化、不涉及数据库、不涉及模板渲染。这是最纯粹的框架性能测试考的是路由分发、请求解析、响应写入这整条链路的最小开销。压测命令如下wrk -t 8 -c 256 -d 60s --latency http://127.0.0.1:3000/ping跑出来的数据是一个很好的参照基线。下面这组数据是本次测试环境下的实测参考值不代表所有机器都会得到同样的结果但相对差异是多轮测试中稳定复现的。框架吞吐量 (req/s)p50 延迟 (ms)p99 延迟 (ms)CPU 使用率Fastify (Node)79,5001.24.6约 90%FastAPI (Python)4,8004.112.8约 50%Gin (Go)88,2000.93.1约 85%Actix-Web (Rust)183,0000.41.9约 95%Spring WebFlux (Java)15,3002.815.2约 60%Laravel Octane (PHP)8,6005.624.1约 45%这个结果基本符合预期Actix-Web 在这轮里是硬核之王Rust 的零成本抽象和编译期优化体现得淋漓尽致。Gin 紧随其后Go 在吞吐和延迟之间找到了很好的平衡。Fastify 受限于 Node 单线程事件循环的吞吐上限即便开多进程也没能超过 Go 和 Rust。FastAPI 单 worker 本身吞吐就不高多 worker 之后线性提升但平均下来每核产出依然一般。Spring WebFlux 的成绩不亮眼其中一部分原因是持续 60 秒的压测对 JVM 来说还是太短GC 和 JIT 优化还没完全进入稳态。如果把压测拉长到 15 分钟WebFlux 的吞吐会逐步攀升这是 JVM 系应用的一个特点也是很多人跑分时容易误解的地方。3.2 第二轮JSON 序列化增加真实感真实 API 不可能永远返回一个pong字符串JSON 序列化才是最常见的高频操作。这轮场景固定返回一段结构体{message:hello,timestamp:1234567890}所有框架都使用各自的 JSON 序列化库。为了公平我不做任何手工拼字符串的优化完全走框架默认路径。这轮压测暴露了更多细节。Fastify 用 fast-json-stringify 能根据 schema 预编译序列化函数速度很快在 Node 生态里几乎没有对手。FastAPI 的 Pydantic v2 表现也不差Rust 底层的序列化能力确实硬但 Uvicorn 的整体调度开销把优势吃掉了大半。Spring WebFlux 使用 Jackson由于反射和类型推断的开销JSON 序列化的吞吐比空路由又降了一截。数据表格如下仍是本次环境的参考值框架吞吐量 (req/s)p50 延迟 (ms)p99 延迟 (ms)Fastify (Node)62,7001.96.2FastAPI (Python)3,9005.817.3Gin (Go)76,4001.14.1Actix-Web (Rust)165,2000.52.4Spring WebFlux (Java)11,8003.721.8Laravel Octane (PHP)6,9007.233.6JSON 序列化确实拖慢了所有框架但拖慢的幅度并不相同。Actix-Web 用了 serde编译期就确定了序列化路径Gin 使用标准库encoding/json反射带来的损耗比 serde 大不少Fastify 虽然预编译 schema但数据在 JS 对象和 JSON 字符串之间的转换仍然有成本。这里要聊一个 MySQL 性能调优里特别常见的话题如果接口的大部分时间都花在 JSON 序列化上调优策略应该是“少序列化”而不是“换更快的 JSON 库”。比如给大列表接口加分页、裁剪不必要的返回字段、开启压缩这些手段对吞吐的提升往往比换库大。跑分只能帮你找到基线业务优化还得靠场景判断。3.3 第三轮模拟数据库查询贴近真实业务第三轮给所有框架接入同一个 PostgreSQL 实例准备一张 10 万行的测试表每次请求执行一次SELECT id, title, created_at FROM items WHERE id $1然后以 JSON 格式返回。这轮测试考的不只是 Web 框架还包括数据库驱动、连接池、查询执行等整条链路的协作能力。为了让数据更有参考性我把连接池配置统一为“最大连接数 15”这是考虑到 8 核机器上 worker 数量和每个 worker 的并发连接数做出的折中。连接池设置过低会直接拉垮所有框架的吞吐设置过高则会把 PostgreSQL 打爆出现连接等待导致 IO 延迟飙升。更多时候性能瓶颈从 Web 层转移到了数据库层MySQL 性能调优的经验在这个环节非常适用慢查询日志先开着索引是否命中一眼就能看出来。最终数据如下框架吞吐量 (req/s)p50 延迟 (ms)p99 延迟 (ms)Fastify (Node)18,3007.528.5FastAPI (Python)2,70018.263.7Gin (Go)22,1005.923.2Actix-Web (Rust)24,6005.129.6Spring WebFlux (Java)9,20012.446.8Laravel Octane (PHP)5,10014.352.2引入数据库之后框架之间的差距被大幅压缩。Actix-Web 的绝对优势从空路由的 2 倍差距缩小到不到 15%因为性能瓶颈已经转移到数据库查询这一环节。这个现象很有现实意义如果你的业务接口都是纯计算或纯转发框架性能决定天花板只要涉及数据库、第三方 API、文件读写那么 Web 框架再快也救不了慢查询。这轮数据里我格外关注了 IO 表现。压测过程中用pidstat -d 1 60观察发现当并发上去之后数据库所在磁盘的 util 一度冲到 90% 以上应用服务器的 IO 反而很健康。这也解答了很多人的困惑“为什么接口突然变慢IO 性能明显下降了” 很多时候不是应用服务器磁盘坏了而是数据库层面的 IO 被慢查询或者全表扫描占满了排查思路要立刻从应用代码转向数据库侧。4. 数据背后的真相为什么快为什么慢跑分只是起点理解快慢背后的机制才算真正入门。同样是一台 8 核机器Actix-Web 能跑出比 FastAPI 高几十倍的吞吐这背后是编程语言、运行时模型、内存管理方式的三重差异。4.1 并发模型事件循环、多线程与 actor 的博弈Node 和 Python asyncio 走的是事件循环路线单线程内用异步 I/O 实现高并发通过“非阻塞 回调/协程”在等待 I/O 时切换任务。这套模型非常节省线程资源但所有 CPU 计算仍然必须在一个线程上串行执行。空路由压测时Fastify 的 CPU 使用率能维持高位但单核的吞吐上限就是上不去这就是事件循环模型的物理边界。Go 的 goroutine 和 Rust 的线程模型本质上是多线程并行可以把负载分散到多个核心上。Gin 和 Actix-Web 在基准测试里能线性扩展吞吐核心原因就是它们的运行时能同时利用 8 个核。Spring WebFlux 同样是事件循环模型但 Netty 的事件循环可以配置多个线程而且 JVM 的线程管理由操作系统原生支持所以扩展性比 Node 单进程好很多。一句话总结高并发场景下能不能“吃满多核”是框架吞吐量的分水岭。单线程事件循环再高效也有不可逾越的峰值多线程并行模型的上限则要高得多。4.2 序列化和内存分配隐藏的魔鬼JSON 序列化的性能差异主要取决于三个因素是否编译期预生成序列化代码、是否大量使用反射或动态类型推断、以及序列化时产生了多少临时对象。Rust 的 serde 在编译期就通过 trait 推导生成解析和序列化代码零反射、零动态分发速度自然最快。Go 的encoding/json大量依赖反射每序列化一个对象都要做类型遍历所以比手动拼字符串慢不少。Java Jackson 因为历史包袱和类型擦除序列化过程中会创建大量中间对象GC 压力越大延迟抖动越明显。FastJSON 之类第三方库做过优化但安全性问题需要额外关注。内存分配同样不可小觑。Node 的 V8 引擎有分代 GC对象创建频繁时会触发 Minor GC遇到大对象就会 Major GC 停顿p99 延迟的忽高忽低多半就是 GC 引起的。Rust 没有 GC也没有运行时内存管理完全靠编译期所有权规则在压测数据上表现为稳定且平坦的延迟曲线。这一点在长稳测试里优势尤其明显。4.3 JIT 与 AOT预热决定了你能看到多好的成绩Java 这种 JIT 编译语言代码首先解释执行热点代码达到阈值后才编译成机器码。JVM 的 C2 编译器能达到很不错的峰值性能但预热时间需要数十秒甚至几分钟。这也是很多 JVM 框架在短周期压测里“吃亏”的原因。Spring WebFlux 如果压测时间从 60 秒拉长到 600 秒成绩会明显改善。Go 和 Rust 是 AOT 编译语言编译出来的二进制直接是机器码启动即可达到峰值性能没有任何预热成本。这是它们在冷启动和短时突发流量场景下的巨大优势。如果你的业务是 Serverless 或函数计算每个实例可能只存续几分钟JIT 类框架根本来不及预热就被销毁了那么 AOT 编译语言会是更理性的选择。FastAPI 属于解释型语言路径本质上没有 JIT 优化也不会像 JVM 那样越跑越快。Python 的优势完全体现在开发效率和生态上指望它扛住极限并发并不现实。理解这些底层差异比单纯背跑分数字重要得多。5. 调优的前提是排查实测中常见的坑跑分和真实业务之间隔着一整片原始森林没有任何一个线上项目能只靠框架本身跑出基准测试的分数。这一章记录我在压测和调优过程中踩过的高频坑以及对应的排查思路。5.1 连接数耗尽TIME_WAIT 是隐形杀手第一次用 wrk 连续压了 3 分钟结束后立刻做第二轮压测发现吞吐量直接下降 40%一开始以为是框架状态被搞坏了后来查了一圈才发现是客户端机器上的 TIME_WAIT 连接堆满了。HTTP keep-alive 如果没做好每个请求都会新建 TCP 连接断开后就进入 TIME_WAIT 状态端口被占用大量资源。排查方法是用ss -s统计 TCP 各状态连接数如果 TIME_WAIT 数量上万就需要在测试机上开启端口复用sysctl -w net.ipv4.tcp_tw_reuse1 sysctl -w net.ipv4.tcp_fin_timeout15生产环境也有类似问题尤其是大量短连接请求的场景比如手机 App 频繁上报数据这时候除了内核参数调整更推荐用长连接池和连接复用来从源头规避。5.2 数据库连接池配置不当线程等锁比查库还慢第三轮压测第一次跑的时候我把连接池设成了“每个 worker 40 个连接”开 8 个 worker 就是 320 条连接。数据库本身扛得住但压测过程中 p99 延迟直线上升问题出在应用侧的连接等待连接池一旦被打满每个请求都要排队获取连接排队时间直接叠加到接口延迟里。经验值是把连接池最大连接数设为CPU 核数 x 5左右8 核机器取 40 个连接作为上限就够了。连接数不是越大越好因为数据库服务端的线程调度、锁竞争都会随着连接数上升而恶化。配合慢查询日志能很快定位到底是查询慢还是获取连接慢。这类问题在 MySQL 性能调优中尤其常见如果监控显示Threads_running高位运行多半就是连接池和慢查询的叠加效应。5.3 日志同步写盘悄悄拖垮吞吐的元凶很多框架默认开启请求日志Fastify 默认 logger、Gin 默认 Logger 中间件、Django/Flask 也各有日志输出。基准测试时这些日志都会被关掉但切回生产环境后有些人习惯性保留全量请求日志结果吞吐量直接腰斩。这背后是磁盘 IO 在作祟。每一条请求日志都是一次写盘操作同步模式下应用线程必须等待落盘完成才能继续处理下一个请求。压测时用pidstat -d可以看到 IO 占用率居高不下应用的 CPU 反而在等磁盘。解决办法是把日志级别限制到 WARN或者使用异步日志写入框架比如 PHP 的 Monolog 就支持 buffer 批量写入效果非常明显。5.4 压测工具自身成为瓶颈数据不准的第一嫌疑当被测框架吞吐超过 15 万 req/s 时wrk 所在机器的 CPU 也可能被打满压测结果就失真了。我用top观察过wrk 的多线程在高并发下自身 CPU 占用可以到 400% 以上这时候测出来的数字已经不能代表框架的真实水平。解决办法有两种一是用性能更强的机器单独跑压测二是减小 wrk 线程数、增加连接数把压力合理分摊。还有一种验证方法是用两套不同的压测工具做交叉测试比如 wrk 的数据和 hey 的数据对比如果两者差距在 5% 以内基本可以确定数据可靠。这个环节容易被忽略但恰恰是保证结论可信的基础。5.5 常见问题速查表现象可能原因快速排查命令解决思路高并发下吞吐骤降TIME_WAIT 堆积ss -s开启 tcp_tw_reuse启用长连接p99 延迟飙升日志同步写盘pidstat -d 1异步日志限制日志级别数据库场景吞吐低连接池耗尽show processlist;缩小连接池增加连接复用JVM 接口越跑越快JIT 预热对比长稳压测数据压测前充分预热多 worker 无法提升吞吐共享内存型锁竞争pidstat -d观察 CPU绑定核心或改用多进程隔离压测结果不稳定wrk 自身瓶颈top看 wrk CPU用 independent 压测机或减小线程数这张表我整理成了团队内部的手册每次做性能调优之前先按表排查一遍能省下大量无效时间。性能优化实战的核心不是上来就改代码而是先用工具定位瓶颈到底在哪个环节再针对性地动刀。6. 基于业务选框架而不是基于跑分选框架三轮压测跑完如果只问“谁才是真正的速度王者”答案在数据上非常明确Actix-Web 在这套环境、这三个场景里是峰值吞吐和延迟表现的最强者。但技术选型永远不能只盯着王者这个位置还要看业务特点、团队技术栈、部署成本、以及长期维护的隐性代价。如果做的是高并发网关、实时计算服务、或者是单机需要扛几十万并发的基础组件Rust 系框架的优势非常值得投入。前提是团队能够接受 Rust 在这个阶段的学习曲线。如果团队主力是 JavaScript 或 TypeScriptFastify 是性价比极高的性能选择它几乎不需要改变开发习惯就能在 Node 生态里做到很优秀的吞吐量。Go 的 Gin 则是综合实力最稳的选手上手门槛低、部署简单、性能长期保持在第一梯队绝大多数云原生项目的合理选择都在这附近。Python 后端在性能上的短板很现实但 FastAPI 的开发速度和生态成熟度仍然是很多内部系统、AI 服务、需要快速迭代的业务的首选。把 Python 服务用在低频管理后台、异步任务、机器学习推理接口上是非常合理的方案没必要让它和 Rust 硬拼空路由吞吐。Spring WebFlux 和 Laravel Octane 虽然在这轮测试中排名靠后但在各自生态内仍然是积极的性能优化实践适合 Java 和 PHP 技术栈深厚的团队继续沿用。我的个人体会是跑分数据能帮你排除明显不适合的选项但决定最终方案的永远是“运行在什么场景、谁来维护、未来怎么扩展”。建议每个团队都把这套压测流程固化下来用自己真实的业务接口、真实的请求模型跑出一份属于自己的性能基线。有这份基线之后再遇到“要不要换框架”“要不要用 Rust 重写”这类灵魂拷问就能用数据说话而不是靠直觉和口水仗。最后再分享一个小技巧压测数据归档时一定要连同 wrk 版本、内核参数、CPU 调节器状态、框架版本、依赖锁文件一起记录。几个月后再跑一轮你会惊觉同样的代码、同样的场景数据漂移有多严重。性能测试最值钱的部分从来不是某个时刻的峰值数字而是可复现、可追踪、可对比的长期工程习惯。