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 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
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
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
Over the past few months, I’ve been rewriting it — in Rust.
This is an interesting test case for Rust, because we’re very much in C/C++’s
home court here: the demo runs on the bare metal, without an operating system,
and is very sensitive to both CPU timing and memory usage.
The results so far? The Rust implementation is simpler, shorter (in lines of
code), faster, and smaller (in bytes of Flash) than my heavily-optimized C++
version — and because it’s almost entirely safe code, several types of
bugs that I fought regularly, such as race conditions and dangling pointers, are
now caught by the compiler.
It’s fantastic. Read on for my notes on the process.
This is a position paper that I originally circulated inside the firmware
community at X. I’ve gotten requests for a public link, so I’ve cleaned it up
and posted it here. This is, obviously, my personal opinion. Please read the
whole thing before sending me angry emails.
tl;dr: C/C++ have enough design flaws, and the alternative tools are in good
enough shape, that I do not recommend using C/C++ for new development except in
extenuating circumstances. In situations where you actually need the power of
C/C++, use Rust instead. In other situations, you shouldn’t have been using
C/C++ anyway — use nearly anything else.