Single-threading for simplicity


Aside for when implemented correctly and when really needed, multi-threading is often a go to for lazy or amateur developers with an uneducated perception that it would boost performance and make the program run faster.

There was a guy who used to ask me to review his code, nothing fancy, just some stuff he wrote to practice programming. Every code base he sent for review had for some reason the same boiler plate for “multi-threading” which I did not even bother to see if it was at least done “properly” as I always rolled my eyes when I see the mess. One project literally was bound to REST rate limits, but he still bombarded the API with thousands of requests each sent in its own thread, because he genuinely believed that it was helping.

Spawning threads is effortless, synchronizing them is difficult. You will have to worry about race conditions, dead locks, while maintenance and debugging cost increases, and turn the project harder to test and conceptualize. Not a fun time, threading should be at the bottom of the list of optimization routes. In fact, this could hurt performance, if multiple threads interact with a shared object, they’ll block each other, effectively rendering them useless. Additionally, threaded programs are more prone to cache misses, due to cache invalidation after a context switch, trashing out hardware level optimization years of engineering tried to squeeze out.

I am all for simplicity, so single-threading when possible is welcomed. But first, we need to know when threads are commonly used, in which I can think of two situations: waiting for I/O or offloading heavy operations where blocking the main thread for a period of time is not an option.

If your threads do nothing but wait for something to happen and act upon it, you’ll be better off relying on an event loop. Consider libevent or write your own. Your target operating system should offer methods for I/O multiplexing, non-blocking calls and asynchronous I/O, so take advantage of those as well. For the other case where the task is indeed CPU-bound, I honestly have no problem with using threads here.

Keep it simple, your initial solution should not involve more threads. Avoid this unwanted complexity, and give it some thoughts on how to approach it when you’re out of choice.

Articles from blogs I read Generated by openring

  • Ugh. Drew’s blogging about Rust again. – You I promise to be nice. Two years ago, seeing the Rust-for-Linux project starting to get the ball rolling, I wrote “Does Rust belong in the Linux kernel?”, penning a conclusion consistent with Betteridge’s law of head…

    via Drew DeVault's blog
  • About eight years ago, I was playing a game of Codenames where the game state was such that our team would almost certainly lose if we didn't correctly guess all of our remaining words on our turn. From the given clue, we were unable to do this. Altho…

    via danluu.com
  • First Livestream Soon

    I’ve recently decided that I’m going to do a livestream. This livestream is mostly just a test, but feel free to stop on by if you want to. I have no idea what to expect…so I’ll see how this goes. The stream will start on August 7 at 5:30 PM (EST). The link i…

    via Bryce Vandegrift's Website