[Python-ideas] The async API of the future

Sturla Molden sturla at molden.no
Fri Nov 2 22:29:09 CET 2012


Den 19. okt. 2012 kl. 18:05 skrev Guido van Rossum <guido at python.org>:

> An issue in the design of the I/O loop is the strain between a
> ready-based and completion-based design. The typical Unix design
> (whether based on select or any of the poll variants) is usually
> ready-based; but on Windows, the only way to get high performance is
> to base it on IOCP, which is completion-based (i.e. you start a
> specific async operation, like writing N bytes, and the I/O loop tells
> you when it is done). I would like people to be able to write fast
> event handling programs on Windows too, and ideally the only change
> would be the implementation of the I/O loop. But I don't know how
> tenable that is given the dramatically different style used by IOCP
> and the need to use native Windows API for all async I/O -- it sounds
> like we could only do this if the library providing the I/O loop
> implementation also wrapped all I/O operations, andthat may be a bit
> much.


Not really, no.

IOCP might be the easiest way to get high performance on Windows, but certainly not the only.

IOCP is a simple user-space wrapper for a thread-pool and overlapped (i.e. asynchronous) i/o. There is nothing IOCP can do that cannot be done with a pool of threads and non-blocking read or write operations.

Windows certainly has a function to select among multiple wait objects, called WaitForMultipleObjects. If open files are associated with event objects signalling "ready-to-read" or "ready-to-write", that is the basic machinery of an Unix select() function.

Then the problem is polling for "ready-to-read" and "ready-to-write". The annoying part is that different types of files (disk files, sockets, pipes, named pipes, hardware devices) must be polled with different Windows API calls – but there are non-blocking calls to poll them all. For this reason, Cygwin's select function spawn one thread to poll each type of file. Threads are very cheap on Windows, and polling loops can use Sleep(0) to relese the remainder of their time-slice, so this kind of polling is not very expensive. However, if we use a thread-pool for the polling, instead of spawing new threads on each call to select, we would be doing more or less the same as Windows built-in IOCPs, except we are signalling "ready" instead of "finished". 

Thus, I think it is possible to get high performance without IOCP. But Microsoft has only implemented a select call for sockets. My suggestion would be to forget about IOCP and implement select for more than just sockets on Windows. The reason for this is that select and IOCP are signalling on different side of the I/O operation (ready vs. completed). So programs based on select ans IOCP tend to have opposite logics with respect to scheduling I/O. And as the general trend today is to develop for Unix and then port to Windows (as most programmers find the Windows API annoying), I think it would be better to port select (and perhaps poll and epoll) to Windows than provide IOCP to Python. 


Sturla


More information about the Python-ideas mailing list