上一版测完总觉得哪里不对,于是改了配置又跑了一遍——这次结果老实多了。

前言:为什么重新测了一遍

这篇文章其实是第二版了。上一篇发出来之后我越想越不对劲——当时每个容器只给了 512MB 内存,fd 上限也没显式调高,跑 10K 并发的时候实际上根本没撑到一万个连接。wrk 报了一堆 connect 8983 错误,真正建立的有效连接也就一千出头,所谓的"高并发 10K"测试本质上测的还是千级并发。那组数据里 Hical 高并发"遥遥领先"的结论,现在看有水分。

这次我把配置拉满了:每容器 1024MB 内存nofile 上调到 65536,VM 内核参数也做了对应调优(somaxconntcp_max_syn_backlog、端口范围等),确保 wrk 发起的一万个连接能真正建立起来。同时精简了文章的对比范围——压测还是 6 个框架一起跑的(数据完整保留在文章末尾),但本文只聚焦 Hical、Drogon、Cinatra 三个第一梯队选手做深入分析。这三个在上一版常规场景里已经拉开了和其余框架的差距,继续带着 91 QPS 的 cpp-httplib 同框只会让图表失真。

结果确实和上次不一样,尤其是高并发部分的排名翻了个个儿。先把结论放在前面:常规负载下三个框架打得很近,但各自有各自的强项——Hical 在 JSON 和中间件场景领先,Cinatra 在纯吞吐和 JSON Echo 上更快,Drogon 在高并发场景下表现最好。


测试环境

宿主机硬件

项目 配置
处理器 Intel Core i7-11700K @ 3.60GHz(8核16线程)
内存 32 GB
存储 SSD(900 GB)
宿主系统 Windows 10 Enterprise LTSC 2021

虚拟化环境

项目 配置
虚拟化平台 Oracle VM VirtualBox 7.1(半虚拟化接口: KVM)
Guest OS Ubuntu 24.04.3 LTS Server
VM 分配 16 GB RAM / 8 CPU
Docker Engine 29.4.3 + Compose v5.1.3
每框架容器 4 CPU + 1GB RAM,nofile=65536
压测工具 wrk 4.1.0(独立容器),4 线程
默认并发 100 连接
持续时间 30 秒
编译器 GCC 14.2(Ubuntu 24.04)
优化级别 Release(-O2)
采样方式 每场景连续跑 3 轮,取算术平均值

注:所有框架运行在同一台 VM 的 Docker 容器中,wrk 也在同一 Docker 网络内发起请求(容器间通信,无宿主机网络栈介入)。VirtualBox 虚拟化会引入一定开销,绝对 QPS 数值会低于裸机,但各框架的相对排名通常稳定。

框架版本

框架 版本 构建方式 I/O 模型 JSON 库
Hical v2.6.3 复制源码编译 C++20 协程 (Boost.Asio) Boost.JSON
Drogon v1.9.8 源码编译 回调 (Trantor) JsonCpp
Cinatra latest FetchContent C++20 协程 (自有实现) iguana

基础场景:Hello World / JSON

先看最简单的纯文本和 JSON 响应,这基本测的是框架自身的"底层开销"——HTTP 解析、路由匹配、响应序列化这些。

场景 Hical Drogon Cinatra
Hello World (GET /) 153,871 140,536 165,717
JSON 响应 (GET /api/status) 141,499 95,090 128,391
JSON Echo (POST /api/echo) 123,585 69,343 131,440
路径参数 (GET /users/42) 140,285 86,487 125,262

单位:Requests/sec(三轮平均值)

几个观察:

  1. Hello World:三者都在 14w~17w 的水平,Cinatra 166k 略高,Hical 154k,Drogon 141k。Cinatra 和 Hical 差距 8%,属于同一档;Drogon 稍低一些。

  2. JSON 序列化(GET /api/status):Hical 141k 领先,Cinatra 128k 紧随,Drogon 95k 落后较多。这里有个重要背景:Drogon 用的是 JsonCpp 库,而 Hical 用 Boost.JSON,Cinatra 用 iguana。JSON 库本身的性能差异直接体现在这里。

  3. JSON Echo(POST 反序列化+序列化):Cinatra 131k 略快于 Hical 124k,iguana 的反序列化确实快。Drogon 只有 69k,差距比较明显,大概率是 JsonCpp 的开销。

  4. 路径参数:Hical 140k 最高,Cinatra 125k 次之,Drogon 86k 偏低。

小结:不涉及 JSON 的话 Cinatra 最快,一旦碰 JSON 就是 Hical 的地盘。Drogon 吃了 JsonCpp 的亏,不过 Hello World 纯吞吐也就比前两个低 10% 左右,不至于掉队。


中间件场景:真正的分水岭

中间件测试是这次最有意思的部分。为了公平,测试分了两种模式:

  • 原生中间件:Hical 用 RouteGroup 洋葱链,Drogon 用 HttpFilter,Cinatra 因为没有运行时中间件机制,用 std::function 调用链模拟等价开销。
  • Hical SyncMW:Hical 独有的同步中间件快速路径(全 Sync 时零协程帧,纯栈调用),其他框架继续用各自的原生机制。
场景 Hical Drogon Cinatra
0 层中间件 140,837 106,789 132,121
3 层(原生) 136,302 105,171 131,595
10 层(原生) 93,402 104,942 137,830
3 层(Hical SyncMW) 141,160 94,588 129,701
10 层(Hical SyncMW) 139,685 100,652 127,711

单位:Requests/sec(三轮平均值)

这里有个很值得讨论的现象:

Hical 的原生异步中间件在 10 层时性能下降明显(从 0 层的 141k 掉到 93k,降幅 34%),而 Drogon 和 Cinatra 几乎不受影响。为什么?因为 Hical 的洋葱模型中间件每层都是一个 co_await,10 层就是 10 次协程挂起/恢复 + 10 个协程帧的堆分配。Drogon 的 HttpFilter 是回调链(不走协程),Cinatra 的测试代码是普通函数调用链——人家根本没有协程帧开销。

但这也是为什么 Hical 提供了 SyncMW 快速路径的原因。当所有中间件都使用 SyncBeforeHandler 且 handler 本身也是同步签名时,RouteGroup 会直接注册为 SyncRouteHandler,走 dispatchSync() 路径——零协程帧,整条链路从中间件到 handler 都是纯栈上函数调用,和 Drogon/Cinatra 的回调/函数调用模型站在同一起跑线上。QPS 从 93k 恢复到 140k,完全消除了协程帧开销,和 0 层中间件的 141k 持平——因为 SyncMW 路径连路由分发本身的协程帧都省了。

公平性说明:Cinatra 在中间件测试中使用的是 std::function 调用链模拟,而不是框架原生的中间件机制(Cinatra 的 middleware 是编译时模板,不支持运行时动态添加)。这意味着 Cinatra 的中间件数字测的是"函数调用链的开销",而非框架中间件调度本身的开销。这是测试设计上的限制——不同框架的中间件机制差异太大,很难做到 100% 等价对比。


高并发:1000 和 10000 连接

这是最能体现框架"韧性"的测试。

并发连接数 Hical Drogon Cinatra
100 137,522 145,663 159,519
1,000 63,077 81,646 69,797
10,000 59,451 100,534 63,971

单位:Requests/sec(三轮平均值)

注:10,000 并发时 Cinatra 三轮均出现 timeout(808~2719 个),Hical 第一轮有 1112 个 timeout 后两轮无错误,Drogon 第一轮有 4022 个 timeout 但后两轮几乎为零。

这组数据很有意思:

  • 100 并发:Cinatra 160k 略高,Drogon 146k,Hical 138k。三者差距在 15% 以内。
  • 1000 并发:所有框架都有较大衰减。Drogon 82k 表现最好,Cinatra 70k 次之,Hical 63k。
  • 10000 并发:Drogon 101k 一骑绝尘,是 Hical(59k)和 Cinatra(64k)的 1.6~1.7 倍。

这组结果我没预料到。跑之前我以为 Hical 的 SO_REUSEPORT + 多 io_context 架构在高并发下会有优势,结果被 Drogon 的回调模型按在地上。两个 C++20 协程框架(Hical 和 Cinatra)在 10K 连接下都掉到了 60k 附近,而 Drogon 稳在 101k。协程模型下每个连接维护一个协程帧,一万个帧的管理和调度本身就是开销,Drogon 的回调模型不存在这个问题。

另外要提一嘴:Cinatra 在 10K 时三轮都有数百到数千个 timeout,这也会拖低 QPS。Hical 除了第一轮外零错误但 QPS 同样低,说明瓶颈不在连接管理而在协程调度本身。


延迟对比

除了 QPS,延迟也很重要:

场景 Hical Avg Drogon Avg Cinatra Avg
Hello World (c=100) 1.91 ms 1.71 ms 1.77 ms
高并发 1000 14.94 ms 12.28 ms 15.37 ms
高并发 10000 157.22 ms 65.86 ms 89.80 ms

数据来自 wrk 的 Avg Latency 输出,三轮平均值。

c=100 时三者都在 1.7~1.9ms,没啥好说的。往上拉就有意思了:

  • c=1000:Drogon 12ms,Hical 15ms,Cinatra 15ms——还在一个量级
  • c=10000:Drogon 66ms,Cinatra 90ms,Hical 157ms——Hical 直接拉胯,是 Drogon 的 2.4 倍

和 QPS 数据对得上,高并发就是 Hical 当前最大的短板,后面得好好优化。


资源占用

指标 Hical Drogon Cinatra
空载内存 200.4 MB 93.5 MB 56.6 MB
满载内存 197.0 MB 93.5 MB 55.8 MB
二进制大小 2.1 MB 1.9 MB 528 KB
代码行数(bench) 149 行 234 行 182 行

Hical 空载就吃了 200 MB,这是 PMR 内存池预分配的代价。好处是运行时几乎不再向系统要内存,坏处是启动就占这么大一坨。Drogon 94 MB,Cinatra 57 MB 最省。

有意思的是三者满载和空载内存几乎没变化——100 并发的压力下连接本身基本不额外吃内存。


综合评价

维度 Hical Drogon Cinatra
常规吞吐 (c=100) 优秀 良好 优秀
JSON 处理 快 (Boost.JSON) 慢 (JsonCpp) 快 (iguana)
中间件 (少量/SyncMW) 最快 良好 优秀
中间件 (大量,异步) 有衰减 稳定 稳定
高并发 (c=1000+) 一般 最好 良好
高并发延迟 偏高 最低 中等
内存占用 高 (200MB) 中 (94MB) 低 (57MB)
生态成熟度 新框架 成熟 中等

几点坦诚的说明

利益相关:我是 Hical 的作者,这个测试从设计到执行都是我一个人干的。Docker 隔离、相同资源限制、wrk 统一配置——这些我尽力做到了,但屁股决定脑袋,测试设计上的视角偏差肯定有。不服的话欢迎自己跑一遍打我脸。

中间件测试其实不太公平:三个框架的中间件机制完全不一样——Hical 是运行时洋葱链、Drogon 是 HttpFilter 链、Cinatra 压根没有运行时中间件。我尽量模拟等价语义了,但严格说测的不是同一个东西。

关于数据波动:每个场景跑了 3 轮取平均。wrk 在 Docker 里的波动大概 5%~10%,三轮能抹平大部分偶然因素,但不可能完全干净。原始数据附在文末,你可以自己看各轮之间的差异有多大。

双层虚拟化的影响:VirtualBox VM 里跑 Docker,绝对 QPS 肯定比裸机低。但大家都在同一个环境里跑,相对排名应该是稳定的。裸机 Linux 上数字会更好看,不过排名大概率不会变。

选框架不能只看 QPS:Drogon 有完整的 ORM、WebSocket、HTTP 客户端;Cinatra 轻巧好上手;Hical 在中间件和 JSON 这块有些自己的想法。性能测试只是选型的一个参考维度,生态、文档、社区活跃度这些才是长期用下去绕不开的。


复现方法

所有测试代码、Docker 配置和压测脚本均已开源在仓库的 benchmark/ 目录下,详见仓库 benchmark/README.md,包含完整的构建、启动、压测、采集和清理流程。

git clone https://github.com/hical61/hical.git
cd hical/benchmark
# 后续步骤参照 benchmark/README.md

注:只需三步就能在你自己的机器上跑出结果。如果和我的数据有明显差异,欢迎开 issue 讨论。


TL;DR

  • 三个框架在 100 并发下性能相近,都在 14w~17w QPS
  • JSON 处理:Hical (Boost.JSON) 和 Cinatra (iguana) 明显快于 Drogon (JsonCpp)
  • 中间件:Hical SyncMW 零协程帧路径最快,但原生异步中间件层数增多时有衰减
  • 高并发 (1000+):Drogon 的回调模型表现最稳健,协程框架都有不同程度下降
  • 内存占用:Cinatra 最低 (57MB),Hical 最高 (200MB,PMR 预分配)
  • 选框架不能只看 QPS,生态和维护同样重要

附录:三轮原始数据

以下是三轮测试的原始 QPS 数据,供交叉验证。每轮为独立的 30 秒 wrk 测试,三轮连续执行,未重启容器。

第一轮(2026-05-25 10:08)

场景 Hical Drogon Cinatra
Hello World (c=100) 156,796.12 127,980.96 163,774.61
JSON 响应 (c=100) 137,491.36 74,466.33 127,707.87
JSON Echo (c=100) 111,098.91 62,833.71 135,691.72
路径参数 (c=100) 150,121.59 88,839.01 118,966.68
中间件 0 层 (c=100) 153,207.23 112,848.48 136,976.94
中间件 3 层原生 (c=100) 136,898.55 110,966.38 138,247.89
中间件 10 层原生 (c=100) 90,629.82 90,728.35 144,136.85
SyncMW 3 层 (c=100) 136,901.79 101,765.38 124,463.02
SyncMW 10 层 (c=100) 141,379.19 99,782.52 125,834.13
高并发 (c=100) 110,907.90 125,923.51 166,994.13
高并发 (c=1000) 62,416.43 82,525.51 73,922.75
高并发 (c=10000) 59,184.07 98,286.46 70,999.25

高并发 10K Socket Errors: Hical timeout=1112, Drogon timeout=4022, Cinatra timeout=2719

第二轮(2026-05-25 10:55)

场景 Hical Drogon Cinatra
Hello World (c=100) 165,965.45 168,045.72 165,510.87
JSON 响应 (c=100) 145,883.87 100,499.66 135,568.09
JSON Echo (c=100) 131,825.18 81,832.00 141,118.30
路径参数 (c=100) 130,455.35 77,424.95 126,874.50
中间件 0 层 (c=100) 138,603.05 99,891.09 121,208.64
中间件 3 层原生 (c=100) 131,093.74 90,841.49 126,053.21
中间件 10 层原生 (c=100) 93,569.44 114,919.03 141,083.12
SyncMW 3 层 (c=100) 149,265.85 80,593.01 127,425.23
SyncMW 10 层 (c=100) 135,342.89 91,646.87 133,061.49
高并发 (c=100) 140,643.56 149,802.87 149,170.97
高并发 (c=1000) 65,478.39 86,809.88 71,551.21
高并发 (c=10000) 59,258.94 94,281.89 62,137.10

高并发 10K Socket Errors: Hical 无错误, Drogon 无错误, Cinatra timeout=919

第三轮(2026-05-25 11:42)

场景 Hical Drogon Cinatra
Hello World (c=100) 138,851.55 125,580.99 167,866.51
JSON 响应 (c=100) 141,122.19 110,304.60 121,898.13
JSON Echo (c=100) 127,830.71 63,364.29 117,510.76
路径参数 (c=100) 140,279.31 93,197.92 129,945.28
中间件 0 层 (c=100) 130,700.88 107,628.47 138,178.82
中间件 3 层原生 (c=100) 140,912.53 113,704.01 130,484.50
中间件 10 层原生 (c=100) 96,007.00 109,177.63 128,268.96
SyncMW 3 层 (c=100) 137,311.12 101,405.52 137,215.18
SyncMW 10 层 (c=100) 142,333.72 110,527.95 124,236.71
高并发 (c=100) 161,013.19 161,261.49 162,390.92
高并发 (c=1000) 61,336.68 75,602.27 63,918.27
高并发 (c=10000) 59,910.86 109,031.90 58,776.93

高并发 10K Socket Errors: Hical 无错误, Drogon timeout=7, Cinatra timeout=1062


测试日期:2026-05-25 | 宿主机:i7-11700K / 32GB | VM:VirtualBox 7.1 + Ubuntu 24.04 (16GB/8CPU) | 容器:Docker 29.4,4 CPU / 1GB per container,nofile=65536 | 工具:wrk 4.1.0 | 每场景 3 轮取平均值

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐