Note: This blog post was originally published by Polymath developer Mudit Gupta on Medium on December 30, 2019.
Rust is a systems programming language that is being developed with safety and speed as its primary goals. It is a highly concurrent modern language with a fast-growing community. Developer surveys like “Stack Overflow Developer Survey” where it has been voted “the most loved language” for four years in a row show the support Rust has been getting. If you are looking for a new language to learn, you should seriously consider Rust. This post talks about the strengths of Rust and why 2020 should be the year you learn Rust.
Rust is one of the very few languages that offer comparable performance to C/C++. Benchmarks consistently show that all other major languages like GO and Java are considerably slower than Rust.
No benchmarks are perfect, but they are a good indicator. Arguably, the most reputed benchmarks come from the Benchmarks Game project, and according to their results, Rust is about three times faster than Go/Java on average.
There is no single reason behind the speed of Rust but a combination of various design decisions. I would like to highlight the ones that I believe made the biggest difference.
1. Aggressive Optimizer
Some languages don’t care about the optimizer much, for example, the official Go compiler barely does any optimizations. It’s not that Go code can not be optimized, gccgo compiler shows that it can be. It’s just that optimizations are not the primary goal of gc developers. That’s not the case with Rust. Since Rust was built with speed in mind, a lot of work has gone into the development of its optimizer. Rust’s optimizer is arguably the most aggressive optimizer out there.
Rust’s optimizer is mean. It only cares about the performance and can sometimes do unexpected optimizations. For example, if you initialize a vector with some values, then use those values, set the original values to zero and delete the vector, you might expect the compiler to unset the actual memory so that the original data can not be accessed by anyone/anything anymore. However, the Rust compiler might optimize away the step that sets the values to zero. This is because not setting the values to zero does not create a side effect in the current program. The compiler sees that you never use the vector after setting the values to zero, so it might skip setting the values to zero to save some time. In that case, the memory where values were stored becomes a scratchpad with “garbage” values and may be used by others in the future. This could be very dangerous if you were setting the value to zero because it contained a secret like cryptographic keys. That secret will now linger around longer and can result in a security vulnerability. This can be prevented by “fake using” data after setting it to zero or using a crate like
Rust uses LLVM to generate assembly code. LLVM is a state-of-the-art optimizer and transformer and is the driving force behind the fierce clang compiler. Apart from the awesome optimization that the Rust compiler does while generating IR, the LLVM optimizer takes it a step further and optimizes the code even more before generating the final assembly code.
2. No garbage collector
How will you feel if you were running a 100-meter sprint, and someone stops you at the 50-meter mark to ask you if you need water? Even though it’s clear that the race will finish at 100-meter and the participants can drink water then, but the water guy was told to make sure that participants are never thirsty. This is essentially what garbage collectors do. They keep poking your data and asking, “You done yet?” This can cause a significant performance drop. Some languages need this performance penalty to offer memory safety.
Thanks to its strong compile-time checks, Rust offers memory safety without any garbage collector. Writing code that plays nicely with garbage collectors takes time and expertise. You don’t need to worry about any of that with Rust.
3. Cache Efficient
Data can either be stored directly (usually in the stack memory) or behind a pointer (pointer in the stack, actual data in the heap memory). Directly stored/cached data can have up to 30 times lower latency than data behind a pointer. This is why caching and efficient data structures are important. Rust does an excellent job with this. For example, when you create a dynamic vector in Rust, not only the pointer to the first element is stored in the stack but also the size and capacity of the vector. This makes fetching length of a vector significantly faster. This indirectly makes other operations like checking out of bounds array access faster as well.
Memory safety guarantees protection against a whole class of bugs that are caused by unsafe memory access such as use after free, dangling pointers, buffer overflow, and race conditions. Languages like C/C++ that allow arbitrary pointer arithmetic with no bounds checking are memory unsafe.
If you use Rust, you don’t need to worry about these bugs at all. Rust’s compiler keeps an eye on every memory location you use or reference and catches any bugs at the compile time itself. If you wanted to, you could mark code as “unsafe” in Rust and do direct memory manipulation but you’ll probably never want/have to do it.
Along with memory safety, Rust also offers type safety. This means Rust will not allow you to mistakenly use a string as an integer and mess everything up.
Rust’s memory safety guarantees allow you to fearlessly and efficiently do concurrent programming. Rust’s notoriously famous borrow checker plays a big role in providing safe concurrency. Thanks to memory safety and ownership checks, Rust’s compiler catches a lot of concurrency errors at the compile time rather than during the execution.
Microsoft’s security engineer, Matt Miller gave a talk at BlueHat security conference earlier this year, where he said that, on average, 70% of security vulnerabilities found in Microsoft’s products were due to memory safety issues. If Microsoft had used a memory-safe language like Rust, all of these issues could have been avoided. Microsoft realizes this, and they are working on developing a Rust-like language of their own.
Tooling and developer community
Rust is a language by the developers, for the developers. Rust comes with a plethora of tools that make a developer’s life easier and safer. Rust has a sizeable and friendly developer community that has created countless tools dedicated to improving the developer experience. Some of my favorite Rust tools include Cargo, Rustup, Rustfmt, Clippy and Cargo Doc.
Libraries and frameworks
Thanks to Cargo and crates.io, Rust has an abundance of surprisingly high-quality libraries that you can plug into your project. Since Rust is a new language, It’s only going to get better from here. There are already over 33,000 crates on crates.io that you can add to your project with a single cargo command.
Apart from libraries that you can plug into your projects, Rust also has a lot of full-fledged frameworks that you can use to fast-track your development. If you need a web framework, go check out Rocket. If you need a blockchain framework, go check out Substrate.
Rust has a relatively steep learning curve because the compiler won’t let you proceed if you write insecure code. You might want to stick to something like Python if you want to spin up a quick Proof of Concept but if you want to write high-quality production code, Rust will probably work much better for you.
Rust is an emerging language with a bright future. If your goal is to write secure, reliable, and performing code, look no further.