*ฅ^•ﻌ•^ฅ* ✨✨  HWisnu's blog  ✨✨ о ฅ^•ﻌ•^ฅ

Compiler optimization options - memchr and ripmemchr case study

Introduction

The inspiration for this post came from a Reddit thread about ReleaseSafe performance in the Zig subreddit.

In that thread a user by the name AldoZeroun was asking why in Rust subreddit people are benchmarking similarly written code in Zig against Rust, but the Zig version was compiled in ReleaseSafe while Rust was compiled in the equivalent of ReleaseFast (opt-level=3 ~ the highest level of optimization in the Rust compiler).

The argument for Zig in ReleaseSafe

The author of the Rust subreddit thread (SaltyMaybe) mentioned ReleaseSafe in Zig is the most similar in terms of runtime safety checks: both have assertions, runtime bounds-checking and other safety checks. That sounds fine, no issues here.

reddit_ReleaseSafe_00

Digging deeper into the code

We are getting to the interesting part where AldoZeroun got the time to rewrite Rust's crate memchr into Zig (let's call it ripmemchr ~ just like grep and ripgrep). Here's the link to the Rust subreddit thread.

reddit_ReleaseSafe_01

Key point in the highlighted part:

"testing on ReleaseFast makes more sense given that almost all the memchr code I'm working from is written under the unsafe keyword, which means rust isn't doing bounds checking at runtime"

'the memchr code is written under the unsafe keyword' --> an argument for compiling the Zig program in ReleaseFast instead of ReleaseSafe if the purpose is to make them as similar as possible.

Here's a different post from AldoZeroun on a similar tone but under the Zig subreddit thread: reddit_ReleaseSafe_02

Conclusion: so which compiler optimization option should we choose?

In the case of writing Zig and Rust programs in order to be able to measure the equivalent / most similar compiler optimization, we need check which crates the Rust program is using and whether it's leveraging the unsafe keyword particularly in hotspots (unsafe has several functions, one of them is to provide extra speed boost).

Coz if they do, then ReleaseFast is more proper comparison and vice versa use ReleaseSafe if the program has no or at least minimal unsafe blocks. For me I'm using ReleaseSafe for compiling my Zig programs and -O2 optimization with lots of safety checks turned on for compiling C programs --> this is because my Rust code are mostly fully safe Rust, unless I'm writing SIMD Rust which is full unsafe.

Bonus: memchr(Rust) vs ripmemchr (Zig)

Codes are taken from AldoZeroun's gitlab repo. Note: 2.5 months have passed between the day I first dig deep into this vs the writing of this blogpost, but looks like I just copy pasted AldoZeroun's Rust code while for the Zig code I did small modification, where I found Aldo's code is unnecessarily too long and verbose...so I modified the code to make it more compact while retaining functionality.

ripmemchr_00 Code repo: Rust, Zig.

Compiler notes:

Here please check by yourself on memchr::memmem has unsafe blocks scattered all over: github link. Lots of functions and types have unsafe keyword.

Comments section here