Skip to content

libuvcpp v1.7.0

Latest

Choose a tag to compare

@github-actions github-actions released this 14 Oct 11:03
· 1 commit to master since this release

下载 (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。