summaryrefslogtreecommitdiff
path: root/lib/net/protocol.rb
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-01-08 00:34:47 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-01-08 00:34:47 +0000
commitb02fc0f9fedd635eb64f4bb6440ab63923c2af24 (patch)
tree07157384354a277ae826bc7a9f035d23e8d75d54 /lib/net/protocol.rb
parent816efa9ae1e6917d488ddf46a76ef40bcb5298a8 (diff)
net/protocol: read directly into rbuf if it's empty
There's no need to allocate a temporary string when @rbuf is empty, we can use it as the read_nonblock destination buffer to save both allocation overhead and avoid a later memcpy. This results in a halving user CPU time and tiny memory reduction with the script below: user system total real before 0.603333 0.539999 1.143332 ( 1.143347) RssAnon: 5624 kB after 0.283334 0.560000 0.843334 ( 0.846072) RssAnon: 5592 kB ------ require 'net/http' require 'benchmark' s = TCPServer.new('127.0.0.1', 0) len = 1024 * 1024 * 1024 * 2 pid = fork do c = s.accept c.readpartial(16384).clear c.send("HTTP/1.0 200 OK\r\nContent-Length: #{len}\r\n\r\n", Socket::MSG_MORE) IO.copy_stream('/dev/zero', c, len) c.close end addr = s.addr Net::HTTP.start(addr[3], addr[1]) do |http| http.request_get('/') do |res| puts(Benchmark.measure { res.read_body(&:clear) }) end end puts File.readlines("/proc/self/status").grep(/RssAnon/)[0] Process.waitpid2(pid) ------ * lib/net/protocol.rb (rbuf_fill): avoid allocation if rbuf is empty [ruby-core:84678] [Feature #14326] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61663 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/net/protocol.rb')
-rw-r--r--lib/net/protocol.rb4
1 files changed, 3 insertions, 1 deletions
diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb
index e1586923c8..380d31ed5d 100644
--- a/lib/net/protocol.rb
+++ b/lib/net/protocol.rb
@@ -172,8 +172,10 @@ module Net # :nodoc:
BUFSIZE = 1024 * 16
def rbuf_fill
- case rv = @io.read_nonblock(BUFSIZE, exception: false)
+ tmp = @rbuf.empty? ? @rbuf : nil
+ case rv = @io.read_nonblock(BUFSIZE, tmp, exception: false)
when String
+ return if rv.equal?(tmp)
@rbuf << rv
rv.clear
return