Rust + Node.js are awesome!

Blazing fast, low requirements, computationally intensive operations on Node.js using Rust

Photo by Mathew Schwartz on Unsplash

Why not JUST Node.js

Just gonna say this, I LOVE Js! The quirks ( 1 == "1" // true ), the new frameworks every week, npm install meaning-of-life , and how X is faster than React.js by Y order of magnitude 😆! Anyways, when I heard about Node.js back in the days of v0.9 it seemed like a dream to have JS Full-Stack! From there my love affair with Express.js started. I have tried RoR and Laravel but a simple copy/paste of business logic from the client to the server or vice versa is enough to keep me here.

But let’s be honest, Node.js is not the fastest kid on the block and poor memory management can be an issue. That happened to me on a project in which my node process was running out of memory on my cheap EC2 instance. Having some background on C and embedded development the obvious problem was the garbage collector of Node.js and the logical solution was to use a language in which I could do manual memory allocation (just… not C!).

That’s when I heard about the new kid on the block, Rust! I’m not gonna sing Rust’s praises here because that’d be a whole different post, but suffice it to say that it is the most loved language on Stack Overflow for a reason! It also wasn’t completely foreign to me (I’m looking at you Go) or a solid but over complicated solution (…C++).

Long story short, the node process that took about ~40s and ~400MB of memory now takes ~3s and ~16MB using Rust. 😎

this , even though it was nice was a little convoluted because the task of the previously mentioned process was to generate JSONs from some CSVs that then were sent to a different Express.js API to server them for the client.

The insight happened when I came across this article on This Week in Rust where the author introduces Neon, a library(?) to call Rust functions from Node.js, in his case from an Electron application, but that got me thinking that I could do the same but from an Express.js app.

It took a little while to get how Neon worked since there are not too many examples of how to use Neon (I know… I will be contributing soon!). I find that Neon is quite logical and functional after getting its general idea, and it provides very nice ways to transfer data back and forth from Js. In a few cases I found it easier to transfer plain strings and have them converted to vectors on Rust using a simple .split(",").collect(); .

An example of this was needing to pass a multidimensional array from Js to Rust. The JsArray API can be a little difficult to understand so I found it easier to encode the data into a DSV (delimiter separated values) thus an array like this [1, 2, [3, 4]] is encoded to 1|2|3,4 and it’s frugal to use, again, the .split() method on Rust to recover that back to a vector.

The last thing that I will share with you that I was elated to discover is how close Rust syntax is to Js. So much so that it didn’t take a lot of effort to migrate my Js algorithms to Rust.

Some JS vs some Rust code

Conclusion

After all this I ended up with a Express.js API with a cool boot time of 3s from using raw CSV files (the JSONs generation became unnecessary) and 8ms of response time! (network delay not included). This is in comparison to the previous version which took a separate process to generate JSONs from CSVs and then server them with a much larger delay. The performance increase is not the only advantage, the consolidation of processes simplifies the deployment strategy, troubleshooting and maintenance. Also Rust is a joy to work on! Take a look at have fun! 🤓