lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Fri, Mar 21, 2014 at 5:29 PM, William Ahern
<william@25thandclement.com> wrote:
> On Fri, Mar 21, 2014 at 03:47:22PM -0700, Coroutines wrote:
> <snip>
>> Just popping in to say IOCP on Windows is like POSIX AIO in that you
>> request an operation be completed and are notified when it has been.
>> With things like select() or epoll() you are notified when a socket is
>> ready for reading, but with IOCP or AIO you are notified when the
>> buffer you pointed the OS at has been filled with the data you wanted
>> to read.  IOCP/AIO should mean less waiting for events to occur
>> because they can handle the two-step process of reading data from and
>> filling a buffer, where usually your program does that.  (This is just
>> an example -- the other side would be telling IOCP/AIO to write data
>> from a buffer to a socket when it can.)  Usually you would
>> select()/poll()/epoll()/kqueue() to be notified when you can write
>> from the buffer out, but the OS can do this faster (which is why
>> people want to like IOCP/AIO).  The only one nobody seems to like is
>> real-time signal IO.  Dude, fuck SIGIO.
>
> IOCP isn't fundamentally any faster. All it does is hide the thread
> synchronization. IOCP has to do the same number of logical operations as you
> would do with epoll + pthreads or with AIO.
>
> IOCP does have some magic regarding how it manages your thread pool by
> controlling the number of outstanding threads doing user-space work, but in
> practice it doesn't buy you anything. If you look at benchmarks people tend
> to get the same throughput with IOCP and they do with epoll, presuming you
> multi-thread your epoll usage.
>
> The _huge_ downside to IOCP (which IMHO far outweights the small
> optimizations) is that it's very difficult to build simple consumer/producer
> frameworks atop it without using callbacks. And callbacks are bug factories,
> especially in combination with threads, because they completely trash code
> locality, among other issues. libevent 2.x continues to fix bugs related to
> callbacks and threading.
>
> IOCP (and AIO, for that matter) lack software composability:
> http://en.wikipedia.org/wiki/Object_composition
>
> It's not just as matter of signaling in an inner loop. Linux, for example,
> allows you to poll an AIO handle. Callbacks hinder composable designs. You
> can't _hide_ a callback, because it obstructs execution flow.
>
> With a non-blocking design, you can implement state machines at the core of
> your consumer/producer object. And you can stack these objects. When you
> switch from a purely threaded design to a non-blocking design, the only
> necessary semantic condition you need to teach your code is "try again".
> With callbacks, you have to _also_ manage interfaces for managing callbacks,
> and all that entails--ownership problems are more difficult, request
> cancellation is problematic, etc.
>
> Example: I have a small socket library in C that does DNS and SSL
> internally. It was trivial to add the features because both my own DNS
> library and OpenSSL handles I/O in a non-blocking manner and _without_
> callbacks. So my so_read() routine can behave _exactly_ like Unix read()
> does. And I can use it everywhere, regardless of the event loop or threading
> framework of the project.
>
> Imagine implementing (and debugging!) the same feature set within an IOCP
> framework. I'd sooner quit my job and work at McDonalds.
>
>

I agree largely with what you have said, I think IOCP/AIO leads to
much complication.  In the interest of getting back to the C++
religious war thingy -- I counter your non-composability argument with
std::function, booyah!