Fearless Non-Concurrency

Last week I wrote my first Rust program!

I've been excited about Rust for a long time, and after finally taking the plunge, I'd like to share some of my thoughts.

Before diving in, let's briefly review what Rust is all about:

And, its biggest selling feature of all:

This makes Rust particularly useful for concurrent/multi-threaded programming, since its compiler prevents many bugs that tend to appear in these circumstances.

A lot has been written about how Rust has enabled developers to parallelize their code relatively painlessly.

But my simple Rust program does not need concurrency. This post is about a Rust port that does not involve parallelization.1

The Program

My program is a simple command-line time-tracker. It reads and writes to an array of log entries stored in ~/.log.json. (Eventually I want to write a Josh Avenier-inspired front-end for viewing the log, but for now logging itself is enough.)

The log program needs to do the following things:

Yes, that's all.

This is something that could probably be solved with a jq-powered shell script, but I wrote the first version using Node.js.

Surprisingly, it was extremely slow. Reading and decoding a nearly-empty JSON file was a serious bottleneck, to the point where even outputting the current in-progress project had a noticeable delay on my laptop (about 1.5-2 seconds). This delay is probably the warm-up time for Node rather than any issue with JSON parsing.

When the goal of your program is to log productivity, it's a little contradictory to have an inefficient logger. The logger should stay out of your way so don't have to spend time waiting for the program to run, possibly losing focus or forcing a context-switch along the way.

Why Rust?

Okay, so the Node version wasn't cutting it. But why use Rust? Why not a language I already know, like Crystal, Lua, Io, or Go?

Well, I knew I wanted to start learning Rust at some point, and this seemed like a good starting point - simple enough to be a good learning tool but complex enough to be challenging. In other words: for a language beginner, log is an achievable challenge.

How'd it go?

The newly Rust-ified version runs significantly faster with no noticeable delay. Mission success!

The Good

Some other positive notes:

The Bad

The Ugly

Closing Thoughts

Overall, I enjoyed learning a bit of Rust. I was able to learn enough to write this (relatively simple) program in one sitting, and even added some trivial features along the way! The syntax took some light adjustment on my part, but I've come to like it. I legitimately had fun writing Rust! I'm sure some of this enjoyment is simply out of novelty, but on the other hand I can't think of a time where I've enjoyed the act of writing C.

Furthermore, Rust forced me to think a little harder about my code, which also helped me uncover a data storage bug, where the Node version would allow you to log events even if they had no project to go to. This bug fix might have more to do with the fact that I rewrote the entire codebase, and less to do with Rust itself.

I think, for now, I will still turn to Crystal if I need to quickly write well-performing code, but Rust has made it onto my radar. I hope to eventually move from Crystal to Rust but until I get used to it, writing in Rust will be slower and more painful than writing in Crystal for me. If I have the time and energy, like I did for log, I might use Rust so I can learn it slowly over time.

And if I ever need to write concurrent code, I'll let Rust do its magic.