Blocking IO cannot have predictable latency under load at very least, you are left at the mercy of OS thread scheduler. Due to various reasons (e.g. mutator threads should not block GC and compiler ones) thread priorities are honored.
I'd argue that a well written NIO (and virtually there are no good open source NIO impl) will beat flat out any blocking. NIO is both faster and offers better/predictable latency under load.
Most impl. use heap ByteBuffer, then parsing requires state machines and often they are simplified by copying the buffers. The blocking IO doesn't really need a state machine as the stack serves that purpose. Then there is some reactive alike pattern (submitting tasks to an ExecutorService) that costs some more latency. Certainly, it's easier to work with and reason about, yet the more hand-outs there are the worse the performance/latency is. There are minor issues like the choice of a good queue. It is an important one as java lacks MultiProducer/SingleConsumer queues out of the box, or even single producer/single consumer. Java does have MP/MC queues (CLQ is an outstanding one) but one has to pay some extra price (incl. false sharing sometimes) to use them.
Ultimately the blocking IO cannot be "faster" than NIO per se since under the hood it uses poll(2)[0] with one socket. Before that it copies the java byte[] to a new location - for smaller byte[] it's the stack. Technically one can blow up the JVM if the stack is very tiny while entering socket.getOutputStream().write(byte[])
Lastly Selector.wakeup() has a stupid issue that involves entering a synchronized block each time even if there is an outstanding wake-up request already. Wakeup requests are implemented via pipes on linux (and a socket pair on Windows) that requires kernel mode switch. During the wakeup all the threads attempting to carry the task block on that very selector for no real reason. It can be played around with a CAS, so only one thread actually enters the monitor.
I will repeat myself blocking IO doesn't have predictable latency and cannot be enforced. In the end it's all about the latency as bandwidth can be bought, more machines deployed but you can't buy latency.
[0]http://linux.die.net/man/2/poll
Some internal stuff on heap vs direct buffer: http://stackoverflow.com/a/11004231
Only couple of downsides: 1) there appears to be the lack of bounded queues and it's a non-trivial one. Bounded queues are important to ensure proper back-pressure on 'producers' and/or killing slow peers. 2) encoding pipeline may require serializing the same message multiple times when sending to multiple clients even if the serialization results into the same byte stream. However this is really a minor issue.
Like I've said I'm pleasantly surprised.
These tests were a particular kind of network traffic, and were testing for max throughput across many connections. Minimizing latency, smaller message sizes, and/or fewer connections can make the decision to use NIO vs standard IO libraries come down in different places. (Not to mention that you cannot program the standard IO libraries in a no alloc form).
DBObject r = collection.find(query);
It blocks while getting the results of the query. If I do something like this: for (int x=0; x < 100000; x++) {
new Thread(() -> DBObject r = collection.find(query))).start();
}
it's going to start 100,000 threads and freeze my computer. However, with Fibers I can do: for (int x=0; x < 100000; x++) {
new Fiber(() -> DBObject r = collection.find(query))).start();
}
and it will work fine since these are lightweight threads (like Go goroutines). I guess my main question is, can I use arbitrary unmodified synchronous code like this to run in Fibers or would the library have to be modified to support it? In this case, would someone have to update MongoDB library to add support for Fibers?If library provides asynchronous APIs, it would yield great performance when integrated with Quasar fibers. If not (like JDBC), it would work as well as it does on regular threads, but won't interfere with all the other great stuff fibers can do.
The opposite canonical example being a static, small-file web server. Short connections. How many files can you serve per second?