select() and at least N bytes readable/writable? - Unix

This is a discussion on select() and at least N bytes readable/writable? - Unix ; In the traditional select() loop, select() will return when at least one byte is available for reading/writing. The problem with this, at least for network usage, is that it tends to result in a lot of very small data chunks ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: select() and at least N bytes readable/writable?

  1. select() and at least N bytes readable/writable?

    In the traditional select() loop, select() will return when at least one
    byte is available for reading/writing. The problem with this, at least
    for network usage, is that it tends to result in a lot of very small
    data chunks being moved, and that in turn results in many passes through
    the corresponding code. This isn't very efficient, better in many
    instances to move one big chunk of 32K bytes (for example) than a much
    larger number of 1400 byte chunks.

    Near as I can tell though, there is no portable way to make select()
    return only when there are at least N bytes available for read/write
    (guarantee a nonblocking read/write of N bytes because that number of
    bytes are present/free in the corresponding buffer). The closest thing
    I have found, available only on some systems, is to use ioctl() with
    SIOCOUTQ/SIOCINQ to probe the sizes of the buffer. But that has to be
    done in a polling mode, which in itself is a waste. Ie, when select()
    returns instead of just reading, use ioctl() to see if the buffer holds
    at least the desired amount of data This gains nothing, because if it
    is not and another select() loop is initiated it will return immediately
    because the 1 byte available/free from the preceding cycle will still be
    there. The various sleep() functions help not at all here since even
    when set to times in the nanoseconds they tend to have real minimum
    sleep times in milliseconds, which is too long for this sort of application.

    Did I miss sometning? Are there functions in recent POSIX (or other)
    standards which provide this desired functionality?

    Thanks,

    David Mathog


  2. Re: select() and at least N bytes readable/writable?

    On Oct 30, 8:41*am, David Mathog wrote:

    > In the traditional select() loop, select() will return when at least one
    > byte is available for reading/writing. *The problem with this, at least
    > for network usage, is that it tends to result in a lot of very small
    > data chunks being moved, and that in turn results in many passes through
    > the corresponding code. *This isn't very efficient, better in many
    > instances to move one big chunk of 32K bytes (for example) than a much
    > larger number of 1400 byte chunks.


    Quite the contrary, it is very efficient because it minimizes latency.
    If the process were CPU limited, it wouldn't get around to doing the
    same thing again until more than 1,400 bytes had built up, so it's
    self-tuning as well.

    This behavior is almost always nearly optimum, and I would take a long
    hard look at whether you're sure you want to mess with it.

    Assume you are CPU limited. This means it will take you awhile to get
    around to sending or receiving. So there will be more bytes to receive
    or more space available for sending. So if you're CPU-limited, you
    will be CPU-efficient.

    > Near as I can tell though, there is no portable way to make select()
    > return only when there are at least N bytes available for read/write
    > (guarantee a nonblocking read/write of N bytes because that number of
    > bytes are present/free in the corresponding buffer). *The closest thing
    > I have found, available only on some systems, is to use ioctl() with
    > SIOCOUTQ/SIOCINQ to probe the sizes of the buffer. *But that has to be
    > done in a polling mode, which in itself is a waste. *Ie, when select()
    > returns instead of just reading, use ioctl() to see if the buffer holds
    > at least the desired amount of data *This gains nothing, because if it
    > is not and another select() loop is initiated it will return immediately
    > because the 1 byte available/free from the preceding cycle will still be
    > there. *The various sleep() functions help not at all here since even
    > when set to times in the nanoseconds they tend to have real minimum
    > sleep times in milliseconds, which is too long for this sort of application.
    >
    > Did I miss sometning? *Are there functions in recent POSIX (or other)
    > standards which provide this desired functionality?


    This would be a significant pessimization. It is almost impossible for
    something special about the way you send data to make it more
    efficient to send larger chunks. If something special about the way
    you receive data makes it more efficient to process larger chunks,
    simply accumulate the chunks in your own buffer and process them when
    it's efficient to do so.

    But odds are you will be CPU-optimizing the case where there is more
    than enough CPU available.

    DS

  3. Re: select() and at least N bytes readable/writable?

    David Mathog writes:

    > In the traditional select() loop, select() will return when at least
    > one byte is available for reading/writing. The problem with this, at
    > least for network usage, is that it tends to result in a lot of very
    > small data chunks being moved, and that in turn results in many passes
    > through the corresponding code. This isn't very efficient, better in
    > many instances to move one big chunk of 32K bytes (for example) than a
    > much larger number of 1400 byte chunks.
    >
    > Near as I can tell though, there is no portable way to make select()
    > return only when there are at least N bytes available for read/write
    > (guarantee a nonblocking read/write of N bytes because that number of
    > bytes are present/free in the corresponding buffer). The closest
    > thing
    > I have found, available only on some systems, is to use ioctl() with
    > SIOCOUTQ/SIOCINQ to probe the sizes of the buffer. But that has to be
    > done in a polling mode, which in itself is a waste. Ie, when select()
    > returns instead of just reading, use ioctl() to see if the buffer
    > holds at least the desired amount of data This gains nothing, because
    > if it is not and another select() loop is initiated it will return
    > immediately because the 1 byte available/free from the preceding cycle
    > will still be there. The various sleep() functions help not at all
    > here since even when set to times in the nanoseconds they tend to have
    > real minimum sleep times in milliseconds, which is too long for this
    > sort of application.
    >
    > Did I miss sometning? Are there functions in recent POSIX (or other)
    > standards which provide this desired functionality?


    What you want is the SO_SNDLOWAT and SO_RCVLOWAT options to setsockopt.
    I'm not sure how widely available they are, however.

  4. Re: select() and at least N bytes readable/writable?

    Nate Eldredge wrote:

    >
    > What you want is the SO_SNDLOWAT and SO_RCVLOWAT options to setsockopt.
    > I'm not sure how widely available they are, however.


    So close, but... (from the socket(7) man page):

    SO_RCVLOWAT and SO_SNDLOWAT
    Specify the minimum number of bytes in the buffer
    until the socket layer will pass the data to the protocol
    (SO_SNDLOWAT) or the user on receiving (SO_RCVLOWAT). These
    two values are initialized to 1. SO_SNDLOWAT is
    not changeable on Linux (setsockopt(2) fails with the
    error ENOPROTOOPT). SO_RCVLOWAT is changeable only
    since Linux 2.4. The select(2) and poll(2) system calls
    currently do not respect the SO_RCVLOWAT setting on Linux,
    and mark a socket readable when even a single byte of data
    is available. A subsequent read from the socket will block
    until SO_RCVLOWAT bytes are available.

    In other words, under Linux SO_SNDLOWAT is not supported at all,
    while SO_SNDRCVLOWAT cannot be used to change the behavior of
    select() for a socket set to nonblocking mode, which is what I wanted it
    for.

    Thanks,

    David Mathog


  5. Re: select() and at least N bytes readable/writable?

    It is unlikely (modulo a stack bug) that you will degenerate to single
    byte at a time. TCP brings data-in in segment quantities and so there
    will typically be a segment's worth of data available when select/poll
    return. There are "nuances" involving the nagle algorithm and the way
    the remote application is calling send of course that mean it may not
    always be a full segment, but it will probably always be at least what
    the application called send with. (modulo the last bits left0over
    after a > MSS send).

    Of course, having said that, a TCP application MUST NOT assume
    send/message boundaries will be preserved by TCP So the code must
    be prepared to handle the case where data does dribble-in one byte at
    a time even though it is unlikely to do so.

    For UDP it will always be a complete UDP datagram's worth of data
    anyway.

    rick jones
    --
    portable adj, code that compiles under more than one compiler
    these opinions are mine, all mine; HP might not want them anyway...
    feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...

+ Reply to Thread