NIO busywaiting

Discussion in 'Java' started by Andersen, Jan 27, 2006.

  1. Andersen

    Andersen Guest

    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?
     
    Andersen, Jan 27, 2006
    #1
    1. Advertising

  2. Andersen wrote:
    >
    > 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
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
     
    Thomas Hawtin, Jan 27, 2006
    #2
    1. Advertising

  3. On Fri, 27 Jan 2006 17:54:52 +0100, Andersen wrote:
    > 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

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
     
    Gordon Beaton, Jan 27, 2006
    #3
  4. Andersen

    Andersen Guest

    Thomas Hawtin wrote:
    >
    > 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();
    }
    }
     
    Andersen, Jan 28, 2006
    #4
  5. Andersen wrote:
    > Thomas Hawtin wrote:
    >>
    >> 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:


    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
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
     
    Thomas Hawtin, Jan 28, 2006
    #5
  6. Andersen

    Andersen Guest

    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.

    >
    > 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
     
    Andersen, Jan 28, 2006
    #6
  7. Andersen

    Andersen Guest

    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.
     
    Andersen, Jan 28, 2006
    #7
  8. Andersen 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?


    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
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
     
    Thomas Hawtin, Jan 28, 2006
    #8
  9. Andersen

    Andersen Guest

    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.
     
    Andersen, Jan 28, 2006
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. dhek bhun kho

    a basic NIO Question

    dhek bhun kho, Jul 26, 2003, in forum: Java
    Replies:
    3
    Views:
    587
  2. Roedy Green

    nio classes

    Roedy Green, Jul 28, 2003, in forum: Java
    Replies:
    1
    Views:
    514
    Thomas G. Marshall
    Jul 29, 2003
  3. Dave Roberts
    Replies:
    0
    Views:
    1,654
    Dave Roberts
    Jul 29, 2003
  4. Avizz
    Replies:
    3
    Views:
    13,840
    Andy Fish
    Sep 29, 2003
  5. iksrazal

    NIO with timeouts != NIO?

    iksrazal, Jun 17, 2004, in forum: Java
    Replies:
    1
    Views:
    6,293
    iksrazal
    Jun 18, 2004
Loading...

Share This Page