介绍
这篇文章的灵感来自于 Reddit 上 Zig subreddit 中关于ReleaseSafe 性能的帖子。
在该帖子中,一个名为 AldoZeroun 的用户询问为什么在 Rust subreddit 中人们要对 Zig 中类似编写的代码与 Rust 进行基准测试,但 Zig 版本是在 ReleaseSafe 中编译的,而 Rust 是在相当于 ReleaseFast 的版本中编译的(opt-level=3 ~ Rust 编译器中最高优化级别)。
ReleaseSafe 中关于 Zig 的争论
Rust 子版块 (SaltyMaybe) 的作者提到,Zig 中的 ReleaseSafe 在运行时安全检查方面最为相似:两者都有断言、运行时边界检查和其他安全检查。听起来不错,这里没有问题。
深入研究代码
我们正要进入最有趣的部分,AldoZeroun 抽出时间将 Rust 的 crate memchr 重写为 Zig(我们称之为 ripmemchr ~ 就像 grep 和 ripgrep 一样)。这是 Rust subreddit 帖子的链接。
突出显示部分中的重点:
“由于我使用的几乎所有 memchr 代码都是用 unsafe 关键字编写的,这意味着 rust 在运行时不会进行边界检查,因此在 ReleaseFast 上进行测试更有意义”
‘memchr 代码是在 ==unsafe== 关键字下编写的’ –> 如果目的是使它们尽可能相似,则在 ReleaseFast 而不是 ReleaseSafe 中编译 Zig 程序的论点。
以下是 AldoZeroun 的另一篇帖子,语气类似,但在 Zig subreddit 主题下:
结论:那么我们应该选择哪个编译器优化选项?
在编写 Zig 和 Rust 程序的情况下,为了能够测量等效/最相似的编译器优化,我们需要检查 Rust 程序正在使用哪些包,以及它是否在热点中利用了不安全关键字(不安全有几个功能,其中之一是提供额外的速度提升)。
因为如果它们确实存在,那么 ReleaseFast 是更合适的比较对象;反之,如果程序没有或至少包含极少的不安全块,则使用 ReleaseSafe。就我而言,我使用 ReleaseSafe 编译我的 Zig 程序,并在编译 C 程序时启用 -O2 优化和大量安全检查——这是因为我的 Rust 代码大多是完全安全的 Rust,除非我编写的是完全不安全的 SIMD Rust。
奖励:memchr(Rust)vs ripmemchr(Zig)
代码取自 AldoZeroun 的gitlab repo 。注意:从我第一次深入研究这个问题到撰写这篇博文,已经过去了 2.5 个月,但看起来我只是复制粘贴了 AldoZeroun 的 Rust 代码,而对于 Zig 代码,我做了一些小修改。我发现 Aldo 的代码太长太冗长了……所以我修改了代码,使其在保留功能的同时更紧凑。
编译器注释:
- Rust:RUSTFLAGS=”-C target-cpu=native -C opt-level=3″ cargo build –release
- Zig:zig build-exe -O ReleaseFast -mcpu=native
–> 按照 AldoZeroun 提到的论点使用 ReleaseFast。
这里请自行检查 memchr::memmem 中是否存在不安全的块: github 链接。许多函数和类型都包含 unsafe 关键字。
原文: https://hwisnu.bearblog.dev/compiler-optimization-options-memchr-and-ripmemchr-case-study/