Re: Java NIO Strategy
Daniel Dyer wrote:
"Why SelectionKey.attach() is evil"
http://weblogs.java.net/blog/jfarcand/archive/2006/06/tricks_and_tips.html
I've read all those and I don't find them at all convincing. Every
accepted connection represents a session, and the session state,
whatever it may be, has to be held somewhere. Why not in the attachment?
And what is it that makes using the key attachment for the session state
'the devil'? And the part about starting a second selector in the same
thread to complete a partial read, introducing another block, is sheer
nonsense. *Not* the way to implement a highly scalable server, thanks.
You already have a Selector: use it! let it trigger when there is more
data, and in the meantime let it handle all the other channels!
What you don't need with NIO is a large read buffer: you can do with
quite a small one, e.g. 1k, if you get the strategy for partial reads
and writes right.
His piece on OP_WRITE has this gem:
while ( bb.hasRemaining() ) {
int len = socketChannel.write(bb);
if (len < 0){
throw new EOFException();
}
}
'This code will works most of the time....until the Selector on which
the SocketChannel has been registered is exhausted, e.g the Selector
isn't able to let the socketChannel flush the content of the ByteBuffer.'
Now (a) write() never returns -1, so what's the test for? (b) Selectors
don't 'get exhausted', and the rest of the last sentence is nonsense. He
explains it further in a response to a comment: 'I means the Selector is
not able to let the socketChannel write its buffer. When this happens,
the socketChannel.write(bb) will return a value of 0, meaning no bytes
were written.' And this is *still* nonsense. Selectors don't prevent
channels from doing anything with their buffers.
What really happens is that the socket send buffer fills up if the
reader is slow, and *this* causes write() to return 0. And once again he
uses a temporary selector to 'solve' this problem. And once again this
is sheer nonsense. He 'clarifies' this two days later in response to
another comment which states the case correctly, blaming tinking in
French/writing in English for the error. Not a plausible explanation.
What you should do is:
while ( bb.hasRemaining() ) {
int len = socketChannel.write(bb);
if (len == 0){
break;
}
}
and then you do the bb.compact(), and then if there are still bytes
unwritten you register for OP_WRITE, otherwise you deregister it. Once
again you let the original Selector do the work so it can handle other
threads in the meantime.
Part IV talks about using multiple threads and multiple selectors so as
'not to overload the main Selector'. What does this mean? Overload the
thread it's running in? There can't possibly be any benefit unless there
are multiple processors and the threads each run in a different
processor. It's just a needless complication otherwise, and I'd like to
see some figures that prove it can be a genuine benefit even in the
multi-processor case. Also in this part he is now recommending using the
key attachment, contradicting what he said in part I.
Very curious set of blogs.