Asynchronous code - why is it needed?

published Nov 11, 2014 01:25   by admin ( last modified Nov 11, 2014 03:42 )

Asynchronous coding is becoming impossible to ignore. There are three main sources for the need for asynchronous programming:

The GUI - Having to deal with asynchronous events is nothing new in GUI programming, it has been a staple of it for decades. Basically humans like to click, type and select in any order they want, and the user interface has to accommodate for that.

The network - In the old days of working with a file on a GUI computer, you would work on a file until it was done, and then you delivered it to your boss. Today, what you work with is often an amalgamation of what you, what your computer well, computes, and what is sent back to you by people and services elsewhere. And since you cannot control when these people and services will get back to you with the results of your request, you need to just to react to it when it happens, if it happens.

Lastly, since we have hit a wall in CPU clock frequency, more performance is achieved by running things in parallel on multiple processing units. Even if these units are closely connected, you will still need to handle asynchronous behavior in order to keep the cores busy.

In a web application you may hit both the network and the CPU. I currently work on a project that needs to push out large amounts of large files, and it often needs to do some advanced maths to decide who gets what. For the file pushing, it is enough to multiplex a CPU core between different output streams without it breaking a sweat, but for the calculations all cores should be busy.

There are different ways of doing asynchronous programming to cater for these different use cases. Some of them are more suited to performance on CPUs, others to GUI or network applications.

One way is to use callbacks, which is used in a  lot of GUI programming and also in javascript by default. A problem with callbacks is that it can be hard to follow the execution of code, since it jumps between different functions as the callbacks are executed. This is sometimes referred to as call back hell. The problem of execution jumping between different blocks of code is somewhat similar to what can be had with exceptions handling and with reverse dependency injection.

Another way of handling concurrency is with futures and promises and building on that, reactive programming. There is also something called software transactional memory. Clojure has software transactional memory and also other constructs for dealing with concurrency on CPUs. Erlang uses the actor model and message passing and pattern matching to get things to work as one system while spread out on different processing units.