Suggestion for setsockopt

Extract from ruby-1.6.8:

static VALUE
bsock_setsockopt(sock, lev, optname, val)
VALUE sock, lev, optname, val;
{
int level, option;
OpenFile *fptr;
int i;
char *v;
int vlen;

rb_secure(2);
level = NUM2INT(lev);   <<<<

I’d like to suggest that if ‘lev’ is provided as a string, then a
getprotobyname() is done to convert it to an integer. Under Solaris and
FreeBSD (at least), constants like ‘SOL_TCP’ are not defined, but you are
supposed to lookup the protocol number in this way.

If this has already been done in the development versions of Ruby, please
excuse the noise :slight_smile:

Regards,

Brian.

I'd like to suggest that if 'lev' is provided as a string, then a
getprotobyname() is done to convert it to an integer. Under Solaris and
FreeBSD (at least), constants like 'SOL_TCP' are not defined, but you are
supposed to lookup the protocol number in this way.

IPPROTO_TCP, ... are not defined on these systems ?

Guy Decoux

Err… yes :slight_smile: The Pickaxe p482-483 doesn’t list them, but they are there
and they work. Problem solved.

Thanks,

Brian.

···

On Mon, Mar 10, 2003 at 02:03:40AM +0900, ts wrote:

I’d like to suggest that if ‘lev’ is provided as a string, then a
getprotobyname() is done to convert it to an integer. Under Solaris and
FreeBSD (at least), constants like ‘SOL_TCP’ are not defined, but you are
supposed to lookup the protocol number in this way.

IPPROTO_TCP, … are not defined on these systems ?

I was playing with setsockopt because I was seeing about a 0.1 second
latency on HTTP requests.

However it seems that the underlying problem is that the Net::HTTP library
sends its request as multiple writes (one for the GET or POST line, one for
each header line, one for the blank line, and one for any POST content if
included)

Coalescing these into a single write is straightforward, so I’d like to
propose that at least GET requests be fixed as follows:

module Net
class HTTPGenericRequest
def request( sock, ver, path )
req = sprintf(’%s %s HTTP/%s’, @method, path, ver) + “\r\n”
canonical_each do |k,v|
req << (k + ': ’ + v + “\r\n”)
end
req << “\r\n”
sock.write req
end
end
end

That still leaves two writes for a POST (one for the headers, one for the
data). My suggested fix is attached; if the POST data is large then it
doesn’t concatenate the header and request, to save building a potentially
large intermediate string.

Doing this reduces the number of network packets sent, gets rid of the
latency problem, and doesn’t require any non-portable setsockopt tweaking.

Regards,

Brian.

httpfast.rb (1.13 KB)

Hi,

In mail “Net::HTTP optimisation (was: Suggestion for setsockopt)”

···

Brian Candler B.Candler@pobox.com wrote:

However it seems that the underlying problem is that the Net::HTTP library
sends its request as multiple writes (one for the GET or POST line, one for
each header line, one for the blank line, and one for any POST content if
included)

Coalescing these into a single write is straightforward, so I’d like to
propose that at least GET requests be fixed as follows:

Agreed. I have commit your suggestion.
Thank you.

Regards,
Minero Aoki

You are welcome!

Although this makes the packet go out with zero delay under Solaris (2.8), I
discovered today that under FreeBSD (4.7) I still get the 0.1 second delay,
unless I also setsockopt TCP_NODELAY. Presumably its Nagling algorithm is
different.

Do you think it’s worth setting this option in Net::HTTP conditionally if
the platform supports it? (Maybe just in Net::HTTP#start?)

If someone tries to do a loop of HTTP requests and only sees 10 per second,
they may think “this darn Ruby scripting language is far too slow” when
actually it’s not Ruby’s fault at all…

Regards,

Brian.

···

On Tue, Mar 11, 2003 at 08:02:26PM +0900, Minero Aoki wrote:

However it seems that the underlying problem is that the Net::HTTP library
sends its request as multiple writes (one for the GET or POST line, one for
each header line, one for the blank line, and one for any POST content if
included)

Coalescing these into a single write is straightforward, so I’d like to
propose that at least GET requests be fixed as follows:

Agreed. I have commit your suggestion.
Thank you.