Speeding up your code by mirroring the CPU

What if I told you your code was primarily waiting for things to happen, rather than doing stuff? Waiting is exactly what happens when you attempt to interact with any component of your system that is a peripheral, so that’s your network, the disk, anything you have connected via USB, Firewire or Thunderbolt. In this article I’m going to talk about how to do other stuff while you’re waiting, to better use the resources available to you, so you can squeeze out the next 100 users from your hardware.

In order to do this I’m going to first talk about the observer pattern.


A popular implementation of the observer pattern is the Event Dispatcher (like Symfony’s). This is a common implementation in which the subject is a the event dispatcher, and the listeners that are executed when certain events are triggered in the dispatcher are the observers.

Sequence Diagram of the observer pattern



Now there are two ways of dealing with this situation. The first is to simply wait for our interrupt to be called before doing anything else. This is the easiest to understand because you’re simply doing one thing after another. However it’s inefficient because you’re constantly waiting.


This is called a non-blocking architecture. This is because we don’t block any other code from running while we’re waiting. There are languages that explicitly support non-blocking code, including, Python, Java, Go, Rust, JavaScript, or Ruby.



Non-blocking systems are fast. However they’re also hard to understand, because any observer can run at any time, it’s often difficult to determine which bits of memory are being read from, or written to. This can lead to complex to debug race conditions.

To make it simpler, we can regiment our architecture with an event dispatcher. An Event dispatcher is a subject that takes messages, and based on the content of these messages, trigger different observers, which when combined with an Event Dispatcher call listeners. An example of one of these messages would be “file read finished”, combined with the content of the file.


Sequence Diagram of the event dispatcher

However inside our system we don’t only want to do low level things. We frequently want to combine a number of low level tasks into a single unit. To this end we can also use an event dispatcher to trigger a more abstract event, such as “user signed up”, allowing us to have the efficiency of low level non-blocking code, for our high level business logic.

