On modern programming languages and growing hardware complexity

I was going to write a blogpost about it, but I can just throw the short version here.

I think the performance story for Rust is not an interesting story.Almost no one cares. I was thinking why I enjoy Rust so much, and the answer is: universality. Rust is always reasonably good choice for whatever I might come up with.

With Rust I can:

  • write an embedded system
  • write a kernel module
  • write a command line application
  • write a native graphics application
  • write a OpenGL game
  • write a web app
  • write a mobile game
  • write a high-performance code
  • write a fast and dirty script
  • (soon) write a client-side webapp
  • embedded it into existing language
  • give it to experienced developers and get great results
  • give it to inexperienced developers and get something that works
  • and so on...

The point is: There is no programming task that can not be done with Rust with a reasonable efficiency. Rust might not be the strongest contender in any specific field, but it is always reasonably close to "the best choice". And in many spaces, the gap is mostly due to immaturity and lack of established solutions, and not the language itself.

Today, I was debugging a crashing PHP tool, that was failing when called from Python test code, when testing my changes to the C++ service calling C library, all communicating with another Scala service.

And I was thinking, this "the right tool for the job" sucks, people. The hardware complexity is nothing, compared to software complexity: explosion of tools, frameworks, platforms, languages etc.

All other languages are making some huge sacrifices to gain some small benefits elsewhere. And Rust... just allows you to have it all.

8 Likes

I slightly disagree. Doing anything related to data science is currently pain in the ass.
But it is problem of libraries, not problem of Rust as a language (except occasional Eye of Sauron here and there).

3 Likes

A lot of what I listed is a PITA right now. But it's not because of the language itself. Just ecosystem immaturity. And considering the age, I think we're doing very well anyway.

1 Like

FWIW C#'s async/await is the "event loop + state machines" solution, and is pretty much the premier implementation of the feature that other languages have drawn from. The only earlier instance I know of is F#'s "asynchronous workflows."

Rust's innovation here is that its state machines are value types- not even C++ has that.

3 Likes

Thanks for the correction. The documentation which I found for this language was somewhat confusing and contradictory in places, with some of it suggesting that stackful coroutines were used.

I think one advantage of Rust which has not been emphasized as much as I think it deserves to be is how constraining ownership is.

At first, it may seem like a disadvantage. If you are used to programming in Java, the inability to whip up an Observer, or store callbacks which reference the object they are stored in, etc... appears crippling. Rust is a stupid language! It forces you to throw away everything you've learned about good design! Arrgh!

I regularly have to deal with well designed Java codebases. They apply DRY religiously, encapsulation reigns supreme, interfaces decorrelate the various parts, event-based observers also help decoupling, and thanks to the GC, ownership is not an issue...

It's a nightmare. I've spent time pair-programming with some of the most experienced developers on those code-bases when bug hunting, and even them struggle to find where the data is coming from, where it's going, and which of the callbacks that got invoked could possibly have modified the object we were inspecting behind our back. The use of a debugger is mandatory, static reasoning being nigh impossible, and even then your brain boils before you can finally manage your head around the data-flow involved in the particular usecase. And finally you understand what is happening. Do not rejoice yet, though, you are only half-way through your ordeal.

For now comes the time to modifying the software to make it behave as you'd need. Remember the part about the nigh impossibility of static reasoning about the program data-flow? Well... if you touch this little part of the program, then, what are the effects? Nobody knows!

Rust solves this issue. "How constraining ownership is" is not glamorous, but the very constraints you chafe against when writing code are a godsend for maintainers. Rust enforces a clean data-flow: no stray references escaping to be used "later". Data flows linearly, in a way that is easy to wrap ones mind around. Limited mutability makes it easy to spot the one/two place(s) where it could get modified.

Ownership is not glamorous, but it's the best thing since sliced bread.

11 Likes

You just recited a functional programming selling point almost word-for-word.

Time is a source of complexity because it adds a bunch of moving parts to our system. We end up having different pieces of data changing at different rates. Therefore, you donā€™t want ā€œmutable stateā€ to be a primitive, but an abstraction you resort to only when you need it, and youā€™ll do it explicitly.

And thatā€™s the most interesting part of it all. Functional programming is associated with concurrency but it was not by design. It just happens that, by making the complex parts of our system explicit, solving more complicated issues like concurrency becomes much simpler.

Edit: remove rant

1 Like