This post is about my first practical experience of acquaintance with the language. To make the post not completely boring, I did benchmarking to compare the implementations based on r2d2, bb8 crates, and ASP.NET.
It can not be an exhaustive overview because I am not a professional Rust developer. And of course I will not tell anything new about the language. But I think people who are interested in Rust should keep the interest and promote it.
So, after ten years of development and five years after the official release Rust should be mature enough. Right? When it has been ranked as the “The Most Loved Programming Language” for five years in a row(!), you should definitely try it.
And I’ve tried. I’ve created two simple projects to learn it. In my research, I discovered some facts about Rust that I find interesting.
First. No one really knows why the language has such a name, and it is likely that even Graydon Hoare, the author of the language, does not know it. The working version is that it’s named after the kind of a fungi.
And second. Rust may seem revolutionary to some people, but one of the creators of the language said:
… we’ve tried hard to avoid incorporating new technology into it. We haven’t always succeeded at failing to be novel, but we have a rule of thumb of not including any ideas in the language that are new as of the past ten years of programming language research…
And I find this very wise. There are so many “hipsters” in the industry these days, and many projects are doomed from the beginning just because the main goal of such developers is “to try out a new technology” rather than to solve a problem. I believe that with such a “rusty” logic, the language has a bright future.
My first Rust project
I started by building a simple CLI. It is a naive implementation of a genetic algorithm that looks for an “optimal” balance of keys on a keyboard. Here is a piece of code from it:
This is the core logic of the application. It takes a certain population as the input, mutates it, recombines the best offspring, and returns them for the next iteration. Piece of cake. You don’t even need to know Rust to understand it!
As you can see, it is easy to read and very expressive. A classic imperative or OOP implementation would require a lot more code. And you may notice that it has a parallelism enabled on the lines with into_par_iter. It uses rayon crate, and this is a great example of the language’s capabilities and extensibility. The idea is very similar to AsParallel from PLINQ in .NET.
When I wrote this code, I was very impressed because it felt like you were writing in a high-level language like C# or TypeScript. Functional programming capabilities are very impressive for a system-level language!
Comparison with ASP.NET
Since I’m mostly a .NET developer I was curious how it performs in comparison with ASP.NET platform. I expected to see that the Rust implementation will outperform C#.
For this I have implemented a simple web server that can add and return notes from PostgreSQL. I also added an endpoint that returns the current date to have some logic without I/O. I chose actix because it is one of the fastest web frameworks for Rust.
It took me less than an hour to implement the .NET version, which is just 55 lines of code, including all blank lines and line breaks, but it took me more than a day to implement the Rust version. This is too much even considering that I am new to this technology stack. And the code that I ended up with to is at least twice as verbose.
My implementation was originally based on r2d2. It’s a generic connection pool for Rust. And since r2d2_postgres does not support asynchronous execution, I used the actix_web::web::block function to execute requests on the thread pool. Here is the implementation of the get_note method:
There is nothing criminal in this code. Yes, it’s verbose, but it’s clear that there are no over-engineering and overhead costs. So it should be fast. I thought.
Always profile when considering optimization!
Yes, the end point of getting the date is slightly faster on actix, but the difference is negligible. It was a surprise for me. I thought the reason was because I don’t have normal async.
So I decided to try bb8. It’s similar to r2d2, but designed for asynchronous connections. The code that I’ve got at the end is even more verbose. Apart from the complexity and fights with the compiler, I ran into another annoying Rust quirk. In order to use some “obvious” features, like asynchronous closures, you have to use nightly build to enable unstable features.
But even bb8 is cuter, it is only slightly better than r2d2. ̶E̶m̶p̶i̶r̶e̶ Microsoft is still winning.
Most likely, the reason is the notorious I/O operations. Either it’s because of immature libraries, or because nightly builds are slower than stable builds. I don’t know. The fact remains. An average developer like me won’t get the performance gain from using Rust when building a web api server.
Probably I did something wrong. I will be happy if someone tell me how to improve it. When you create a web api server, the programming language is not the most important thing, apparently. However, pure computations on Rust should be faster.
No matter what, I really enjoyed coding in Rust. I will continue to use it if I need to write efficient calculations or garbage collection will be a problem.