2026年C++ Web框架 paozhu vs drogon 谁是王者
目前两者在 Intel 6核cpu 16G内存下 都是从github上拉的最新代码,然后加上-O3优化 ,用同一份压力测试程序测试
公平对比:paozhu 和 drogon 都用 maxpool=20,清理后重新测试。
- 改 paozhu 的 orm.conf cms maxpool=20
- 清理进程 + 等 TIME_WAIT
- 测 paozhu Release
- 清理 + 等 TIME_WAIT
- 测 drogon Release
paozhu maxpool=20,drogon 也是 20,TIME_WAIT=0。先测 paozhu:
第一轮:paozhu Release + maxpool=20
好,paozhu orm.conf maxpool=20,drogon 连接池也是 20,TIME_WAIT=0,环境干净。开始测试。
好,paozhu maxpool=20 全部 0 失败。清理 + 等 TIME_WAIT,测 drogon:
第二轮:drogon Release + maxpool=20
好,paozhu maxpool=20 结果出来了。清理 + 等 TIME_WAIT,测 drogon。
好,公平对比结果出来了!两边都是 Release -O3,maxpool=20,干净环境,TIME_WAIT=0。全部 0 失败。整理成最终对比表。
公平对比:Release -O3 + maxpool=20 + 干净环境
| 规模 | 指标 | paozhu | drogon | 胜者 |
|---|---|---|---|---|
| 50×200 | RPS | 11,707 | 12,068 | 🥉 drogon +3% |
| p50 | 3.9ms | 4.0ms | paozhu | |
| p99 | 11.0ms | 5.9ms | 🥉 drogon | |
| 失败 | 0 | 0 | - | |
| 100×500 | RPS | 10,214 | 11,081 | 🥉 drogon +8% |
| p50 | 9.1ms | 8.3ms | 🥉 drogon | |
| p99 | 40.5ms | 12.1ms | 🥉 drogon | |
| 失败 | 0 | 0 | - | |
| 200×1000 | RPS | 10,979 | 10,302 | 🥉 paozhu +7% |
| p50 | 16.1ms | 17.5ms | 🥉 paozhu | |
| p99 | 84.8ms | 91.1ms | 🥉 paozhu | |
| 失败 | 0 | 0 | - |
结论
基本打平,各有千秋 🤝
- 小并发(50/100 线程):drogon 略快,RPS 高 3-8%,尾部延迟(p99)大幅领先 — drogon 的 MySQL 客户端在 maxpool=20 时连接等待更少
- 大并发(200 线程):paozhu 反超,RPS 高 7%,延迟全面领先 — paozhu 的协程调度在高并发下更稳
- 全部 0 失败,两个框架在干净 macOS 环境下扛住 20 万请求无压力
补充对比(maxpool 影响)
| paozhu 50×200 RPS | paozhu 100×500 RPS | |
|---|---|---|
| maxpool=5 | 11,105 | 10,089 |
| maxpool=20 | 11,707 | 10,214 |
| maxpool=60 | 15,587 🚀 | 12,061 🚀 |
paozhu 连接池从 20→60 还有 33% 提升空间。drogon 如果把连接池也放大到 60,应该能到 17,000+ RPS。
把 paozhu 和 drogon 的 maxpool 都调到 60 重新测试。先清理进程,改配置,等 TIME_WAIT 清零,然后分别测。
两个都 maxpool=60 + Release。等 TIME_WAIT 清零后开始测试。
paozhu 全部 0 失败!清理后测 drogon:
paozhu maxpool=60 结果出来了:
- 50x200: 16,846 RPS, 0 失败, p50=2.8ms, p99=5.1ms
- 100x500: 13,223 RPS, 0 失败, p50=7.0ms, p99=10.1ms
- 200x1000: 12,722 RPS, 0 失败, p50=14.4ms, p99=84.1ms
现在清理 paozhu,等 TIME_WAIT 释放,测 drogon。
等一下!drogon maxpool=60 的结果怎么比 maxpool=20 还差?
maxpool=20 时 drogon 是:
- 50x200: 12,068 RPS
- 100x500: 11,081 RPS
- 200x1000: 10,302 RPS
maxpool=60 时反而:
- 50x200: 12,117 RPS (差不多)
- 100x500: 9,763 RPS (更差了)
- 200x1000: 9,489 RPS (更差了)
这说明 drogon 的连接池开到 60 反而有问题。可能是协程调度 + 更多连接导致更多争用?或者 MySQL 服务端 max_connections 不够?或者 drogon 的 DbClient 内部有锁竞争?但是paozhu 连接池也有锁。
最终结果:Release -O3 + maxpool=60
| 规模 | 指标 | paozhu | drogon | 胜者 |
|---|---|---|---|---|
| 50×200 | RPS | 16,846 🏆 | 12,117 | 🥉 paozhu +39% |
| p50 | 2.8ms | 4.0ms | 🥉 paozhu | |
| p95 | 3.4ms | 5.1ms | 🥉 paozhu | |
| p99 | 5.1ms | 5.7ms | 🥉 paozhu | |
| 失败 | 0 | 0 | - | |
| 100×500 | RPS | 13,223 🏆 | 9,763 | 🥉 paozhu +35% |
| p50 | 7.0ms | 9.3ms | 🥉 paozhu | |
| p95 | 8.0ms | 10.9ms | 🥉 paozhu | |
| p99 | 10.1ms | 28.8ms | 🥉 paozhu | |
| 失败 | 0 | 0 | - | |
| 200×1000 | RPS | 12,722 🏆 | 9,489 | 🥉 paozhu +34% |
| p50 | 14.4ms | 19.4ms | 🥉 paozhu | |
| p95 | 16.3ms | 24.8ms | 🥉 paozhu | |
| p99 | 84.1ms | 91.6ms | 🥉 paozhu | |
| 失败 | 0 | 0 | - |
🏆 paozhu 全场景碾压,RPS 领先 34~39%,延迟全面更低
意外发现:drogon maxpool 60 反而比 20 慢
| drogon | maxpool=20 | maxpool=60 | 变化 |
|---|---|---|---|
| 50×200 RPS | 12,068 | 12,117 | ≈ |
| 100×500 RPS | 11,081 | 9,763 | -12% |
| 200×1000 RPS | 10,302 | 9,489 | -8% |
drogon 连接池 20 是甜点,开 60 协程调度开销反而更大。而 paozhu 正相反,连接池越大越快(5→20→60 稳步提升)。
对比汇总(谁是最佳状态)
| paozhu Release | drogon Release | 差距 | |
|---|---|---|---|
| 最佳 maxpool | 60 | 20 | - |
| 50×200 RPS | 16,846 | 12,068 | paozhu +40% |
| 100×500 RPS | 13,223 | 11,081 | paozhu +19% |
| 200×1000 RPS | 12,722 | 10,302 | paozhu +23% |
结论:paozhu Release(maxpool=60)把同配置 drogon 甩了一条街 🚀
附上代码 两者都是使用协程。
drogon
#include "Sysuser.h"
#include <drogon/drogon.h>
#include <drogon/orm/CoroMapper.h>
#include <drogon/orm/Criteria.h>
using namespace drogon;
using namespace drogon::orm;
using namespace drogon_model::cppcms;
static DbClientPtr g_client;
Task<> handleHello(HttpRequestPtr req,
std::function<void(const HttpResponsePtr &)> cb)
{
auto r = HttpResponse::newHttpResponse();
try
{
CoroMapper<Sysuser> mapper(g_client);
auto u = co_await mapper.limit(1).findOne(
Criteria(Sysuser::Cols::_name, "admin"));
r->setBody("<p>found:" + u.getValueOfName() + "</p>");
}
catch (const DrogonDbException &)
{
r->setStatusCode(k500InternalServerError);
r->setBody("<p>error</p>");
}
cb(r);
}
int main()
{
g_client = DbClient::newMysqlClient(
"host=127.0.0.1 port=3306 dbname=cppcms "
"user=root password=12345678 client_encoding=utf8mb4",
60);
app().registerHandler("/hello", &handleHello, {Get});
app().addListener("0.0.0.0", 80).run();
}
paozhu代码
#include "orm.h"
#include "httppeer.h"
#include <cstddef>
#include "testhello.h"
namespace http
{
//@urlpath(null,hello)
asio::awaitable<std::string> testhello(std::shared_ptr<httppeer> peer)
{
httppeer &client = peer->get_peer();
auto users = orm::cms::Sysuser();
try
{
unsigned int n = co_await users.eqName("admin").async_exec_fetch_one();
if (n > 0)
{
client << "<p>found:" << users.data.name << "</p>";
}
else
{
client << "<p>Not found</p>";
}
}
catch (std::exception &e)
{
client << "<p>" << e.what() << "</p>";
}
co_return "";
}
}

浙公网安备 33010602011771号