From b02fc0f9fedd635eb64f4bb6440ab63923c2af24 Mon Sep 17 00:00:00 2001 From: normal Date: Mon, 8 Jan 2018 00:34:47 +0000 Subject: 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 --- lib/net/protocol.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 -- cgit v1.2.3