From: aci10@eng.cam.ac.uk (A.C. Innes)
Newsgroups: comp.os.os2.advocacy
Subject: Merits of Async I/O (was Re: OS/2 vs NT features list, Revision 1.3)
Date: 3 Sep 92 21:10:18 GMT
Organization: Cambridge University Engineering Department, England

brian%jaguar.cs.utah.edu@cs.utah.edu (Brian Sturgill) writes:
[I wrote previously:]
>>This is neither a flame nor a correction, but rather a simple request
>>for information.  Could you (anyone) please give an example or
>>explanation as to why asynchronous I/O is "better" (easier to use,
>>more efficient, whatever) than using synchronous I/O in a separate
>>thread?  Perhaps I simply misunderstand the reasons for wanting to do
>>async i/o, but why would it not be just as easy (or easier) to spawn a
>>separate thread to handle "background" writes or reads as to set up
>>signal handlers to respond to read/write completion events (presumably
>>by initiating more async read/writes)?  In other words, isn't async
>>i/o something that was provided to make up for the lack of
>>multi-threading, at least for one particularly useful application of
>>threads?
>
>You are right in that in many cases they are equivalent.  However sometimes
>this can be quite inefficient.
>
>Let's assume one has a server that reads 1K of data, quickly analyses it
>and stores some value.  Let's suppose it's not unreasonable that the server
>might have to service 100 clients at a time and that the data comes in
>via file handles.
>
>Threaded approach... fork 100 threads, each has it's own 1K buffer.
>Here you have the overhead of 100 threads and 100 1K buffers.
>
>Async I/O approach... issue 100 async reads each calling the same routine
>for I/O completion.  Here you need the overhead of recording the 100 async
>reads (8 bytes per?), one thread, and only the number of reads actually
>being done at that instant's worth of 1K buffers (assuming the
>read_is_ready routine allocates the buffer on the stack).

Unless you know something I don't.... :-)
I think you will need 100 i/o buffers in either case, because you have
no idea in which order the async requests might finish, so you must
provide a separate buffer for each request (I am going by the BSD-type
specs I have seen).

So the real difference comes down to the extra (primarily) memory
overhead for having 100 threads (I am assuming that the threads
already exist, so creation time is not a factor) versus the complexity
and potential inefficiency of the signal handler that must cope with
multiple independent asynchronous requests.  I contend that even if
the signal driven approach has similar performance to the threaded
approach, the signal driven method is actually conceptually
implementing multi-threading, although the code for the signal
handler (and the main code that must interact with it) must be pretty
hairy.  As jin meng mentioned in another post, with the async approach
the program will have to use some kind of data structure to keep track
of all the requests (clients), which the signal handler will need to
interact with.  This extra work, plus the work needed to deal with
potentially multiple requests for each signal generated, may in the
end make the threaded approach faster.

It would be interesting to see what the relative performance
of threaded vs. async signal-driven approaches is under a 
system (NT) that implements both.  (I presume that NT implements
async i/o "properly", not using threads behind the scenes.)

To put it another way: if you were implementing a client/server
system of the kind you describe above, would you rather program
it to use async i/o or would you use threads?

--
Andrew Innes (aci10@eng.cam.ac.uk)
Engineering Dept.
Cambridge University
Cambridge, England.
Newsgroups: comp.os.os2.advocacy