In this series so far, we’ve taken a C program and converted it into a faster,
smaller, and reasonably robust Rust program. The Rust program is a recognizable
descendant of the C program, and that was deliberate: my goal was to compare and
contrast the two languages for optimized code.
In this bonus section, I’ll walk through how we’d write the program from scratch
in Rust. In particular, I’m going to rely on compiler auto-vectorization to
produce a program that is shorter, simpler, portable, and significantly
faster… and without any unsafe.
In part 4 we took the unsafe code that deals with treating
arrays of f64 as arrays of vectors, and we corralled it into a safe API.
In this installment, we’ll look at the remaining reasons why advance is an
unsafe fn, and make it safe — not by removing all the unsafe, but by
narrowing it down.
This one’s a doozy — the remaining changes to advance are hard to
separate, so I’ve packed them all into one section. Now is probably a good time
to refill your coffee.
In part 3 we found that our use of uninitialized memory was a premature
optimization that didn’t actually improve performance. This left us with only
one remaining unsafe function, but, boy, is it a doozy.
In this part, I’ll begin the process of corralling its unsafe optimizations
into more clearly safe code, by replacing arbitrary pointer casting with a
lightweight abstraction.
In part 2 we introduced Rust references, and this was enough to convert
one of our inner functions into safe Rust.
The others are still unsafe. There are several reasons for this. In this, the
briefest of sections, we’ll tackle the easiest one: deliberate use of
uninitialized memory.
In the first part of this tutorial we took an optimized C program and
translated it to an equivalent Rust program, complete with all the unsafe
weirdness of the original: uninitialized variables, pointer casting and
arithmetic, etc.
In this section, we’ll begin using Rust’s features to make the program
incrementally more robust, while keeping performance unchanged.
Specifically, we’ll begin by introducing references.
In this part of the series, we’ll take a grungy optimized C program and
translate it, fairly literally, into a grungy optimized unsafe Rust program.
It’ll get the same results, with the same performance, as the original.
LRtDW is a series of articles putting Rust features in context for low-level C
programmers who maybe don’t have a formal CS background — the sort of
people who work on firmware, game engines, OS kernels, and the like. Basically,
people like me.
I’ve added Rust to my toolbelt, and I hope to get you excited enough to do the
same.
Let the compiler do the work: a bonus section that looks at how
we’d write the program idiomatically in native Rust, and rely on
auto-vectorization to make it fast.