I had been meaning to learn Rust since I first toyed with Go a couple of years ago. During this period, I’ve written a non-trivial amount of Go code both inside and outside Google, but never found the chance to sit back and learn Rust.
This changed a month ago during my yearly family trip to Korea. This time around, I decided upfront that I would not work on any personal or work projects for the 2-week long vacation. Instead, I would focus all spare time in reading. And I would read “The Rust Programming Language”, second edition. The plan worked: getting through the book took the two weeks and I barely wrote any code.
“Huh, how can you learn a programming language without actually trying it out?” โwell, easy: I did not learn the language. My goal was to get a glimpse of the language’s basic syntax and all it has to offer while mapping its features to the things I already knew about other languages and paradigms. I was specifically interested in understanding everybody’s dread for the borrow checker. This general overview would move my Rust knowledge from unknown unknowns to a mixture of known knowns and a lot of known unknowns. This way, when actually using the language down the road, I would be aware of all its features and I would know where to head for more information.
And here I am, writing a review. So how did I actually learn the language? I spent last month’s downtime reimplementing sandboxfs in Rust. The original and current implementation is in Go and it is not performing as well as I wished, plus all CPU profiling traces so far point at the Go runtime as the major source of overhead. I wanted to see how well Rust led itself to writing low-level OS software and I wanted to see if its promise of zero-overhead abstractions held true by making sandboxfs faster.
The overall feeling I’ve gotten from Rust is better than the one I got from Go two years ago. Granted, I was already sold on its premises, but it has delivered: the sandboxfs rewrite prototype is already faster than the Go version even when using idiomatic Rust abstractions and without doing any profiling. Furthermore, Rust’s strictness has helped me spot dubious logic in the original implementation during the rewrite. (Disclaimer: the speed differences are likely caused by the differences in the FUSE bindings.) The claim of “if it compiles, it works” is as true as it can possibly be, which is something hard to claim when writing a file system.
In this series, I will provide a more detailed review of the language. Among other topics I’ll cover a few of the unique language properties, Rust’s integration with third-party software, a brief review of the book, and a comparison against Go. I’ll make plenty of comparisons against arbitrary languages throughout the review, but Go deserves special treatment.
Spoiler alert: I’m excited about Rust being a nicer language than the alternatives (where “nicer” means more expressive, safer, and faster) with which to write highly-reliable and efficient systems. I’m hesitant about the maturity of Rust’s libraries ecosystem and even Rust’s own standard library in some cases. I’m uncertain about where I will be able to use it in the future. And I’m well-aware that the learning curve is steeper than for other languages (namely Go).
More on the next post! Be sure to come back for more next week.