Since I first learned to program, a lot has changed in the way computers work. While this fact isn’t always apparent to the user, it means that optimizations I was taught now result in highly suboptimal code. One thing, however, has remained constant: Hard drives are slow.
In recent years, this situation has gotten worse rather than better. CPU speeds have grown faster exponentially, while hard drives have barely managed even a linear speed increase. DMA transfers, becoming common, have widened the gap even more; now CPUs don’t have to do nearly as much work when handling disk I/O.
With the traditional UNIX I/O mechanisms, you issue a read or write system call, and then wait until the call has completed. A typical hard drive takes about 9 ms to position the head and then a little longer to perform the operation—and that’s assuming a linear. A modern CPU runs at least 1 GHz. In the time it takes to position the disk head, a 1 GHz CPU runs for nine million clock cycles. You can get a lot done in that many cycles.
The obvious solution is to dispatch the read or write requests as soon as you know what data you’re going to need, and then do something else while the OS processes the request. The asynchronous I/O (AIO) APIs, provided as part of the POSIX real-time extensions, allow you to do exactly that.
Operating System Support
Commercial UNIX systems have supported POSIX asynchronous I/O. Some of the best documentation currently available comes from IRIX and HP/UX. More recently, Free UNIX variants have started to support it; Linux and FreeBSD both support most of the specification, for example.
Support is slightly different between operating systems. Code using AIO on some platforms, including Linux and Solaris, must be linked with -lrt to provide support for the POSIX real-time extensions. On FreeBSD, AIO support isn’t built into the default kernel and must be loaded as a module with the following command:
# kldload aio
On versions of Mac OS X prior to 10.3, AIO wasn’t supported at all, and until OS X 10.4 AIO operations were supported only on files, not other file descriptor types such as sockets. Using AIO can give significant performance benefits, but it can also increase the testing overhead when porting to new platforms.