From: Francis Cianfrocca Date: 2006-07-17T17:48:50+09:00 Subject: Re: net/http performance Luke Burton wrote: > necessary methods to tweak the buffer size: > > class OverrideInternetMessageIO < Net::InternetMessageIO > def rbuf_fill > timeout(@read_timeout) { > @rbuf << @socket.sysread(65536) > } > end > end > > > I couldn't make any real recommendations on what the buffers size should > be. I imagine it's a trade off between the OS kernel's buffer size, TCP > packet size, and memory footprint of your application. Do HTTP clients > normally automatically negotiate a buffer? Do they pick one based on > content type? What are the common optimisations, and should net/http > follow them? > > I tested a couple of values and found anything past 65536 bytes started > giving negligible returns, on my G5 running OS X 10.4.7 (ruby 1.8.2 - > i.e. the default OS X install). It would be really interesting to get a record of the actual data sizes read out from each of the calls to sysread(65536) in your modified code. If stdout is free, maybe you could do something like: timeout(@read_timeout) { a << @socket.sysread(65536) puts "sysread #{a.length} bytes" @rbuf << a } just for a few trials, especially to compare the values when your large file in coming in from a LAN, a WAN, and the Internet. The values you see should give you a clue as to what the sysread buffer size ought to be. TCP of course has the "sliding congestion window" mechanism in which it adaptively increases the number of bytes that a peer may send to another peer before it must wait for an acknowledgement. Most of the time, this number may not be larger than 64K (because it's carried in a 16-bit field in the TCP packet header), which explains your observation that 64K is a practical limit. With a large file transfer on a fast and otherwise unloaded network, you should see this value quickly reach and remain at 64K. (This is not something that HTTP clients have to do themselves, to your other question- it's built into TCP.) If your application runs on a LAN, I would expect a lot of benefit from 64K sysreads. Across the Internet, I'd be pretty surprised if you get much improvement from sysreads above 16K (which is also the typical network-driver buffer size for Berkeley-derived kernels like OSX, unless you've tweaked yours). It's rather a surprise that the Ruby code which handles these raw reads is so inefficient that cutting down the number of passes through it makes such a difference. I'm usually pretty surprised when I/O processing in an application is more than a negligible fraction of the network transit time. -- Posted via http://www.ruby-forum.com/.