Repository navigation
下载 (Download)
六个平台各一份预编译包,点名字直接下载:
| 平台 | 包 |
|---|---|
mingw-x64 |
libuvcpp-1.7.0-mingw-x64.zip |
mingw-arm64 |
libuvcpp-1.7.0-mingw-arm64.zip |
msvc-x64 |
libuvcpp-1.7.0-msvc-x64.zip |
msvc-arm64 |
libuvcpp-1.7.0-msvc-arm64.zip |
linux-x64 |
libuvcpp-1.7.0-linux-x64.zip |
linux-arm64 |
libuvcpp-1.7.0-linux-arm64.zip |
v1.7.0 重点 (Highlights)
这一版有两条主线:HTTP/1.1 / HTTP/2 / HTTP/3 / WebSocket 的吞吐与常驻内存(v1.6.4
之后的开发档 1.6.5–1.6.61 里陆续落地的,57 档),以及
把「预编译包是全功能的」这句话补完。
这一版快了多少
下面这一组是 HttpArena 平台自己那套装置上的
读数(它的机器、它的生成器),同一个条目、同一种测法,对照的是上一版发布包 v1.6.1:
| 档位 | v1.6.1 |
1.7.0 | 倍数 |
|---|---|---|---|
baseline-h3-64(req/s) |
58 | 1 167 034 | ×20 121 |
echo-ws-pipeline-512 / -4096 / -16384(req/s) |
10.85 M / 12.63 M / 10.63 M | 30.03 M / 28.94 M / 25.18 M | ×2.77 / ×2.29 / ×2.37 |
async-32000(req/s) |
725 202 | 1 513 512 | ×2.09 |
pipelined-4096(req/s) |
3 612 234 | 6 784 375 | ×1.88 |
json-tls-4096(req/s) |
370 872 | 672 436 | ×1.81 |
json-comp-4096(req/s) |
194 410 | 325 476 | ×1.67 |
baseline-4096(req/s) |
1 141 979 | 1 639 189 | ×1.44 |
static-h2-1024(常驻内存) |
3.7 GiB | 793 MiB | ÷4.8(吞吐同时 +54%) |
那一轮 42 档的 5xx 全是 0。全套读数、逐档对照、以及"哪几档一格没涨"
(latency-*、8gbit、async-db 这些被外部因子钉住的档)都写在
doc/benchmark.md 的 §4.5,
含每个数的出处(平台把原始读数提交回条目分支,可复核)与逐条归因 ——
其中 h1/h2 那一组高吞吐档的提升只归到"库侧、1.6.23–1.6.51",没有逐提交归因。
预编译包:差集到此为空
此前"预编译包是全功能的"这句话有一处差集:release.yml 十条配置里
一条都不传 UVCPP_ENABLE_YYJSON 与 UVCPP_ENABLE_BROTLI,而 db 模块的两个远程
后端是显式 =OFF。所以从包里能拿到的能力,比从源码默认构建拿到的少三样。1.7.0 起
差集为空:yyjson、brotli、MySQL、PostgreSQL 都在包里,六条腿一致。
三样东西,三种进包方式
| 怎么进包 | 为什么是这种方式 | |
|---|---|---|
yyjson |
-DUVCPP_ENABLE_YYJSON=ON,走 FetchContent 取源码,以目标文件形式并进同一个 uvcpp 库 |
单头 + 单 .c,没有共享库可链,也没有包要多一个 |
brotli |
-DUVCPP_ENABLE_BROTLI=ON 加 -DUVCPP_BROTLI_FROM_SOURCE=ON |
发现顺序是"先系统后源码"。发布腿不能听天由命:镜像哪天装了 libbrotli-dev,配置期就会静默改走共享库,.so / .dll 上多出三条 DT_NEEDED 而不会有任何一条断言变红(ldd 黑名单里原本也没有 brotli —— 已经补上) |
MySQL / PostgreSQL |
-DUVCPP_ENABLE_DB_MYSQL=ON -DUVCPP_ENABLE_DB_PGSQL=ON 加 -DUVCPP_DB_RUNTIME_LOAD=ON |
见下一节 |
为什么 MySQL/PG 是「编进去、运行时加载」
DT_NEEDED(Windows 上是 PE 导入表)是加载期解析的,不是调用期。所以链上
libmysqlclient / libpq 的后果不是"用到才报错",而是没装这两种客户端库的机器连
libuvcpp.so 都加载不起来 —— 哪怕那个程序只跑 HTTP、一行 db 代码都不碰。1.6.x 的
六个包正是靠把这两个后端关掉来躲开这件事。
UVCPP_DB_RUNTIME_LOAD=ON 换了一条路:两个后端照编进库(mysql.h / libpq-fe.h 在
配置期仍然要,MYSQL_BIND 的布局必须从真的头里读),但客户端库在运行时才
dlopen / LoadLibrary,符号从一张函数指针表上取。于是:
- 没装客户端库的机器上,除"真去连 MySQL/PG"之外一切照常;
- 真去连时拿到的是
uvcpp_db_status::NO_DRIVER加一句写清了试过哪些库名的话,
而不是一句裸的dlopen失败;UVCPP_DB_MYSQL_LIBRARY/UVCPP_DB_PGSQL_LIBRARY
可以指一个明确路径。
这是一处行为变更,写在这里而不是悄悄改:此前"配置期没找到客户端库 ⇒ 那个后端不
存在(宏是 0)",此后是"后端存在,有没有库要运行时才知道"。uvcpp_db_drivers() 在
1.7.0 的包里打印 sqlite,mysql,postgres。从源码构建的人不受影响 —— 新开关默认
OFF,今天的行为逐字节不变。
为了让这条路走得通,构建侧另有三处改动
--exclude-libs,ALL(ELF 上的共享目标)。 本仓在非 Windows 上UVCPP_API是空的,
链进去的静态库符号全部导出。dlopen("libpq.so.5")之后,它那份按系统 OpenSSL 编的
SSL_*调用会先撞上我们导出的那份,同进程两份 libcrypto、一手建一手放 —— 堆损坏。
这个链接选项只藏来自静态归档的符号,我们自己的 API(含uvcpp_c_*的 C ABI)
直接由目标文件构成,照样导出。判据是nm -D里SSL_new/EVP_*/Brotli*归零,
而check_capi_symbols.py与.pc可链接性两条门禁仍绿。- Windows 上的客户端头。 两条 MSVC 腿的镜像上没有 MySQL/PG 的开发头(
windows-11-arm
上连 PostgreSQL 都没有),所以四条 Windows 腿共用一份钉死版本的头:从 MSYS2 的
.pkg.tar.zst(mirror.msys2.org上的不可变 URL)取出来放进C:/client-headers/,
由.github/scripts/win-client-headers.sh做。Linux 两条腿则用
apt-get download libmysqlclient-dev libpq-dev+dpkg -x摆一份头出来 —— 不装包:
jammy 上这两个都Depends: libssl-dev,而发布腿有一条"不装 libssl-dev"的不变量
(22.04 那份是 3.0.2,没有 QUIC API,装上会让find_package静默产出一个坏包)。 - Linux 两条腿不再传
-DUVCPP_STATIC_RUNTIME=ON。 这个开关在 UNIX 上把
-static-libgcc -static-libstdc++同时追加到共享目标与可执行文件的链接行
(CMakeLists.txt里那一段),于是libuvcpp.so与每一个链接它的 C++ 可执行文件
各自带一份 libstdc++ ⇒ 同进程两份。同一份模板实例(std::once_flag/
std::__future_base那一族)是 COMDAT、两边都进导出表,动态解析按"可执行文件优先"
⇒ 一侧的__once_proxy会跳进另一侧的_FUN。2026-10-14 那轮预演 9 条用例当场崩
(5 条 SEGV、4 条 SIGABRT,x64 与 arm64 逐条相同),全是"跨线程 + future/promise"
那一类。这不是用例特有的毛病:把 .so 摆成"静态 libstdc++"、只让用例去链系统那份
libstdc++.so.6—— 也就是任何一个普通使用者的形状 —— 同一条用例照样段错误;
把开关去掉之后这 9 条与整棵 136 条用例零失败(其中 2 条 db 用例因没起数据库而跳过)。
所以"预编译包给别人直接用"与"静态 libstdc++ 的 .so"是互斥的,选前者。代价是 Linux 的
ldd多出
libstdc++.so.6与libgcc_s.so.1—— 装了apt的 Linux 上本来就有(libstdc++6
是apt自己的依赖)。Windows 两条 MinGW 腿照旧开着:PE 没有全局符号作用域,
不存在互相顶掉的问题,而 MinGW 用户机器上未必有libstdc++-6.dll。
断言清单从 13 枚扩到 17 枚
六条腿的模块断言读的是生成的头(<tree>/include/uvcpp/uvcpp_config.h),不是
CMakeCache.txt —— 后者在静默降级时照旧写着 =ON。新增的四枚是
UVCPP_YYJSON_ENABLE、UVCPP_BROTLI_ENABLE、UVCPP_DB_MYSQL_ENABLE、
UVCPP_DB_PGSQL_ENABLE。同一批还加了两条反向断言:Linux 两条腿在 nm -D -u 里
数未定义的 mysql_ / PQ 符号(应为 0),ldd 黑名单补上
libbrotlienc/dec/common 与 mysqlclient / pq。
换包之前
- C++ API 与 C ABI 都没有破坏性改动,C ABI 版本仍是
1。 - 包里的模块集合变大了(
UVCPP_YYJSON_ENABLE/UVCPP_BROTLI_ENABLE由 0 变 1,
uvcpp_db_drivers()由sqlite变sqlite,mysql,postgres),
而 yyjson / brotli / db 这三个后端带来的DT_NEEDED一条没多 —— 这正是上面
那几处构建侧改动的目的。(Linux 上总数多了两条,来自最后那一条改动,与模块无关。) - 自包含的含义要按新的写法理解:Linux 上
ldd libuvcpp.so除 libc 与 C++ 运行时
(libstdc++.so.6/libgcc_s.so.1,见上)之外仍无其他;MinGW 的 DLL 依赖表照样
只有 Windows 自带模块。运行期的例外有两处:真要连 MySQL / PostgreSQL 时那台
机器上得有对应的客户端库;C++ 运行时那份则是基础库,装了apt的发行版本来就有。
本版的逐条说明,以及按主题汇总的完整清单(每条都标出它首次出现的开发档号):
CHANGELOG.md。