What is the status of POSIX asynchronous I / O (AIO)?

There are pages scattered across the network that describe POSIX AIO objects in varying amounts of detail. None of them are terribly recent. It is not clear what they describe. For example, the official site (?) For supporting asynchronous I / O of the Linux kernel here says that sockets do not work, but on the β€œaio.h” manual pages on my Ubuntu 8.04.1 workstation everything seems to imply that it works for arbitrary file descriptors. Then another project that seems to work at the library level with even less documentation.

I'd like to know:

  • What is the purpose of POSIX AIO? Given that the most obvious implementation example I can find is that it does not support sockets, all this seems strange to me. Is it easy for asynchronous disk I / O? If so, why the hyper-generic API? If not, then why is the I / O drive the first thing they attacked?
  • Where are some examples of complete POSIX AIO programs that I can look at?
  • Does anyone really use it, really?
  • What platforms support POSIX AIO? What parts of this do they support? Does anyone really support the implied "Any I / O for any FD" that <aio.h> seems to promise?

The other multiplexing mechanisms available to me are quite good, but the random bits of information floating around made me curious.

+83
linux asynchronous posix bsd aio
Sep 17 '08 at 21:32
source share
4 answers

Network I / O is not a priority for AIO because everyone who writes POSIX network servers uses a non-blocking event-based approach. In the old Java style, "billions of blocking threads" fit terribly.

The disk I / O is already buffered, and reading / entering data from the disk can be pre-programmed into the buffer using functions such as posix_fadvise. This leaves direct, unbuffered disk I / O as the only useful target for AIO.

Direct, unbuffered I / O is really only useful for transactional databases, and they tend to write their own threads or processes to manage their disk I / O.

So, at the end, that leaves POSIX AIO in a position not serving any useful purpose. Do not use it.

+22
Sep 17 '08 at 23:15
source share

The efficient execution of socket I / O was allowed using the ports kqueue, epoll, IO IO and the like. Performing asynchronous file I / O is a kind of late visitor (other than overlapping windows and Solaris I / O for early support for posix AIO).

If you are looking for socket I / O, you are probably better off using one of the above mechanisms.

Thus, the main task of AIO is to solve the problem of asynchronous I / O. Most likely, Mac OS X only supports AIO for regular files, not sockets (since kqueue does this much better).

Write operations are usually cached by the kernel and unloaded later. For example, when the read head of a disk passes by the place where the block is to be recorded.

However, for read operations, if you want the kernel to prioritize and order your reads, AIO is really the only option. This is why the kernel can (theoretically) do this better than any user-level application:

  • The kernel sees all disk I / O, and not just tasks on the application disk, and can order them globally.
  • The kernel (can) know where the head is reading the disk, and can select the reading task that you give it in the optimal order to move the head to the shortest distance.
  • The kernel can use its own queue to optimize your read operations.
  • You may be able to perform more read operations per system call with lio_listio () than with readv (), especially if your reads are not (logically) contiguous, storing a small portion of the system call overhead.
  • Your program might be a little easier with AIO, since you do not need an extra thread to block while reading or writing.

However, posix AIO has a rather inconvenient interface, for example:

  • The only effective and well-supported event callbacks are signals that make it difficult to use in the library, because it means using signal numbers from the global process namespace. If your OS does not support real-time signals, this also means that you need to fulfill all your outstanding requests to find out which one is actually completed (for example, for Mac OS X, and not for Linux). Signal capture in a multi-threaded environment also leads to some complex limitations. Usually you cannot respond to an event inside the signal handler, but you need to pick up the signal, put it on the phone, or use signalfd () (on linux).
  • lio_suspend () has the same problems as select (), it does not scale very well with the number of jobs.
  • lio_listio (), since there is a fairly limited number of tasks that you can go through, and it’s not so easy to find this restriction in a portable way. You must call sysconf (_SC_AIO_LISTIO_MAX), which may fail, in which case you can use the definition AIO_LISTIO_MAX, which is optionally defined, but then you can use 2, which is defined as guaranteed for support.

As for the real application using posix AIO, you can take a look at lighttpd (lighty), which also posted a performance measurement when implementing support.

Most posix platforms now support posix AIO (Linux, BSD, Solaris, AIX, tru64). Windows supports it through overlapping I / O files. I understand that only Solaris, Windows, and Linux really support async. file I / O to the driver itself, while other operating systems emulate asynchronous mode. I / O with kernel threads. Linux is an exception, its posix AIO implementation in glibc emulates asynchronous operations on user-level threads, while its own async I / O interface (io_submit (), etc.) is truly asynchronous up to the driver, assuming the driver supports it .

I find it quite common among OSes not to support posix AIO for any fd, but to limit it to regular files.

+61
Mar 15 '11 at 4:30
source share

The libtorrent developer provides a report on this: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/

+9
Oct 26 '12 at 15:29
source share

There is aio_write - implemented in glibc; the first call to the aio_read or aio_write function generates several user-mode threads, aio_write or aio_read requests for that thread, the thread executes pread / pwrite, and when it is finished, the response is sent back to the blocked calling thread.

Ther is also a "real", supported kernel level (this requires libaio, see io_submit http://linux.die.net/man/2/io_submit ); it also needs O_DIRECT (it may also not be supported by all file systems, but the main ones support it)

see here:

http://lse.sourceforge.net/io/aio.html

http://linux.die.net/man/2/io_submit

Difference between POSIX AIO and libaio on Linux?

+2
Oct 27 '14 at 8:40
source share



All Articles