mold 3.0.0:高速链接器改用 Rust
mold 是高速链接器,3.0.0 是从 C++ 改写到 Rust 之后的第一个大版本。发布说明写明 2.42.1 是最后一个 C++ 版本。3.x 要补上和 GNU ld 的兼容缺口,重点是链接脚本,并为 Linux 发行版把 mold 设为默认链接器做准备。
3.0 按 2.42.1 的替代来做:命令行选项相同,目标架构相同,除下面列出的修复外输出也相同。链接性能与 2.42.1 持平。兼容验证包括各目标的测试套件、一批真实工作负载和选项组合的输出对比,以及构建全部 Gentoo 包。发布说明称没有发现回退。
损坏输入文件时,C++ 版本可能越界读并以段错误退出。3.0 对这些读取做了边界检查,出错时在访问点 panic。自行构建时构建系统已从 CMake 换成 Cargo,需要 Rust 1.95 或更新版本,以及一个 C 编译器。oneTBB 依赖已去掉,仍静态链接 mimalloc 3.5.3;可用 --features system-allocator 改用系统 malloc。启动时不再预留 8 GiB 虚拟地址空间,因此可以在 ulimit -v 下运行。
同名 common symbol 现在取最大尺寸和最严对齐,与 GNU ld、lld 一致。单横线选项按 GNU ld 的方式解析,以前 -entry=main 会被读成 -e ntry=main。AArch64、PPC32、ARM32 上,跨段调用静态函数的 range extension thunk 不再跳到错误地址;发布说明举的例子是 ARM64 Chromium debug 构建。
原文链接:https://github.com/rui314/mold/releases/tag/v3.0.0
1.95 起 overflowing_add 可能被误编译
这是 rustc 的误编译问题,编号 rust-lang/rust#163779,从 1.95.0 开始出现。标签包括 I-miscompile、P-high、A-mir-opt,以及 stable 到 stable 的正确性回退。问题在 SsaRangePropagation:它会从可选 assert 传播范围信息。
优化开启、溢出检查关闭时(默认 release,或 -O),下面这个函数会被编成直接返回 false。函数先调用 std::ops::Add::add,再返回 a.overflowing_add(b).1。MIR 里 AddWithOverflow 后面的 assert 被当成一定成功,LLVM 输出是 ret i1 false。用 + 再调用 overflowing_add 复现不了,需要调用 Add::add 方法。评论指出回退来自 #150309,随 1.95.0 发布。
修复在 #163780,标题是 Skip optional asserts in SsaRangePropagation。该 PR 已合入,issue 已关闭。
原文链接:https://github.com/rust-lang/rust/issues/163779
读多写少负载里逐项 RwLock 的开销
这篇文章测量同一份读多写少负载里,parking_lot::RwLock 和 crossbeam epoch 原子指针的读吞吐。数据模型是 Store = HashMap<u32, Arc<Data>>,Block = Vec<Arc<Data>>。读请求会遍历 Block 里的全部元素。写侧是单线程,每次整份替换 Metrics。
作者选用 parking_lot::RwLock。std::sync::RwLock 的读写优先级交给操作系统,tokio::sync::RwLock 获取时可能让出。这段遍历是同步计算,不希望每读一项都让出。另一种做法是把 Metrics 放在 crossbeam_epoch::Atomic 后面,读者 load,写者 swap 后 defer_destroy。
基准设置:50 个并发 Tokio 读任务,1 个写任务每秒 500 次写,Block 长度 16,384,机器是 Apple Silicon 的 MacBook Air。预热 2 秒,测量 10 秒,5 次取平均。RwLock 读吞吐 15.93k 次/秒,p50 441.42µs,p95 910.18µs,p99 1.81ms。原子指针读吞吐 229.07k 次/秒,p50 22.44µs,p95 49.84µs,p99 241.97µs。关掉写线程后,RwLock 读吞吐是 16.01k 次/秒。
一次 Block 遍历要做 16,384 次读锁获取和释放。按大约 1.6 万次遍历/秒计算,RwLock 内部大约每秒 5.24 亿次计数更新。crossbeam 的 pin() 对整次遍历只钉一次 epoch,每一项只做一次原子指针加载。Block 本身大约每秒插入 1 到 2 次,外层仍用 RwLock<Vec<_>>;Metrics 继续走原子指针时,读吞吐 204.40k 次/秒,p50 26.17µs。基准代码在 sattva9/rwlock-vs-lockfree。
原文链接:https://pranitha.dev/posts/rwlock-vs-lockfree/
ruxen:用 nginx 测试套件校验的 HTTP 服务
ruxen 是实验性的 nginx 行为重实现,读取 nginx 配置,并用 nginx 上游测试套件校验自己的二进制。它只支持 Linux 和 HTTP/1.1,每核一个线程,运行时是 monoio(io_uring),TLS 用 rustls。0.1.1 本周发布,仓库 gvozdetsky/ruxen,安装命令是 cargo install ruxen --locked。作者写明它还不能上生产,也不是逐行翻译 nginx 的 C 代码。
为了跑通 nginx-tests,它要匹配 nginx 的命令行(-c、-p、-g、-t、-T)、PID 文件、信号处理和错误日志格式。目前 opt-in 的 105 个测试文件里,63 个端到端通过。还不能执行的访问限制指令,例如 limit_except、ssl_verify_client on、disable_symlinks,会让进程以 [emerg] 拒绝启动。
性能目标是同一配置下至少达到 nginx 1.24 吞吐的 95%。测试机是 i9-13900HX,wrk -t16 -c512。相对 nginx 1.24:return 200 低 1.0%,反向代理低 1.9%,TLS hello 高 8.0%,8 KiB 静态文件(sendfile 打开)低 11.6%,最后一项低于 95% 目标。已实现静态文件、proxy_pass、keepalive 和故障转移、rewrite / return / if / map、error_page、auth_basic、带变量的访问日志,以及带 SNI 的 TLS 1.2/1.3。还没有 HTTP/2、缓存和模块。0.1.1 修了 6 个私下报告的安全问题。
原文链接:https://github.com/gvozdetsky/ruxen
From Rust中文社区 Mike
社区学习交流平台订阅:
评论区
写评论还没有评论