NIO busywaiting

A

Andersen

How should I use the OP_WRITE flag when using selectors and sockets? It
tells me when the network card is ready for me to write things to it.
The problem is that I do not always have data to write, so the selector
almost busy waits by returning with OP_WRITE ready indicating that it is
ready to accept data, but I have nothing to write, so it busy waits.

How do I solve this?
 
T

Thomas Hawtin

Andersen said:
How should I use the OP_WRITE flag when using selectors and sockets? It
tells me when the network card is ready for me to write things to it.
The problem is that I do not always have data to write, so the selector
almost busy waits by returning with OP_WRITE ready indicating that it is
ready to accept data, but I have nothing to write, so it busy waits.

Remove OP_WRITE from the set of interested ops. Do not remove it from
the selector because that appears to be a very slow operation (certainly
it was back in 1.4, and I don't know of anything happening to change that).

Tom Hawtin
 
G

Gordon Beaton

How should I use the OP_WRITE flag when using selectors and sockets?
It tells me when the network card is ready for me to write things to
it. The problem is that I do not always have data to write, so the
selector almost busy waits by returning with OP_WRITE ready
indicating that it is ready to accept data, but I have nothing to
write, so it busy waits.

How do I solve this?

When you have data to write, call write() without waiting for
OP_WRITE. If write() fails, use OP_WRITE to determine when the channel
becomes writeable again.

Don't use OP_WRITE as long as write succeeds.

/gordon
 
A

Andersen

Thomas said:
Remove OP_WRITE from the set of interested ops. Do not remove it from
the selector because that appears to be a very slow operation (certainly
it was back in 1.4, and I don't know of anything happening to change that).

Please explain more. Because it is indeed being *very* slow. I am just
doing interestOps() on the key to indicate interest for writes or not,
otherwise following the standard pattern of:

while(1) {
int num = selector.select();

if (num==0)
continue;

Set selKeys = selector.selectedKeys();
for (Iterator it = selKeys.iterator(); it.hasNext(); ) {
SelectionKey currKey = (SelectionKey)it.next();
/* PROCESS KEY */
currKey.remove();
}
}
 
T

Thomas Hawtin

Andersen said:
Please explain more. Because it is indeed being *very* slow. I am just
doing interestOps() on the key to indicate interest for writes or not,
otherwise following the standard pattern of:

Do you know what it is spending time on? Is it just going around the
loop continuously?

Much the same as Gordon Beaton says in his reply.

Keep your key registered with the selector throughout. However you need
not be interested in OP_WRITE until you find that you can't write any
more. Just write your buffer out, and see if it fails to be copied out.
When the channel wont accept any more writes, only then do you need to
be notified when it is in a state for further writes.

Unless you have data that you can't written at the moment, then there is
no need to be notified of when you can write data. Selecting with
OP_WRITE will immediately return until you fill the relevant system buffers.

Similarly if you couldn't deal with reading any more data (because your
buffers are full, say), then you should not be interested in OP_READ. Or
if all your worker threads are tied up and you can't take another
connection, don't be interested in OP_ACCEPT.

As a rough approximation, you could write your code not to use OP_WRITE
at all (although it will obviously fail nastily when the relevant system
buffers fill up).

Tom Hawtin
 
A

Andersen

Thomas Hawtin wrote:

I know this, what I do not know is things related to the technology:
Is SelectionKey.interstOps() the right way to change my interest set?
Should I call Selector.wakeup() to ensure that it actually has any
effect? Otherwise some select() statement might be sleeping
indefinitely, not knowing that I am now interested in some events.
 
A

Andersen

Thomas Hawtin wrote:

I know this, what I do not know is things related to the technology:
Is SelectionKey.interstOps() the right way to change my interest set?
Should I call Selector.wakeup() to ensure that it actually has any
effect? Otherwise some select() statement might be sleeping
indefinitely, not knowing that I am now interested in some events.
 
T

Thomas Hawtin

Andersen said:
I know this, what I do not know is things related to the technology:
Is SelectionKey.interstOps() the right way to change my interest set?
Yup.

Should I call Selector.wakeup() to ensure that it actually has any
effect? Otherwise some select() statement might be sleeping
indefinitely, not knowing that I am now interested in some events.

Yes, if you are in a different thread from one that might be within
select() (everything becomes a total nightmare if you try multiple
threads simultaneously selecting).

From the last line of the SelectionKey introduction comments:

"In any case, a selection operation will always use
the interest-set value that was current at the moment that
the operation began."

So the current select() is not notified and should be woken (other
activity on the server may mask the bug).

Tom Hawtin
 
A

Andersen

My problem seems to be thrashing. select() returns with result 0 and
hence I am busy waiting in a loop, making the computer extremely slow.
Select should be blocking, and returning only if I call wakeup(), yet it
keeps returning with result 0 and I am not calling wakeup() all the
time. What can it be? Also, I do have a try {} catch (Exception ex)
surrounding the select() call, but no exception is thrown.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,140
Latest member
SweetcalmCBDreview
Top