ruby-changes:49695
From: normal <ko1@a...>
Date: Sun, 14 Jan 2018 11:44:57 +0900 (JST)
Subject: [ruby-changes:49695] normal:r61812 (trunk): net/http: use writev for HTTP chunked request bodies
normal 2018-01-14 11:44:53 +0900 (Sun, 14 Jan 2018) New Revision: 61812 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61812 Log: net/http: use writev for HTTP chunked request bodies This reduces both user and system CPU time for large uploads with dynamically-generated request bodies. user system total real before: 0.393334 1.580000 1.973334 ( 1.971066) after: 0.223334 0.976666 1.200000 ( 1.198514) ------ require 'socket' require 'net/http' require 'benchmark' nr = 1024 * 1024 * 1024 s = TCPServer.new('127.0.0.1', 0) addr = s.addr at_exit { Process.waitall } fork do c = s.accept # not exactly accurate but fast IO.copy_stream(c, '/dev/null', nr + 500000) begin buf = c.readpartial(16384) tmp = '' until buf.end_with?(-"0\r\n\r\n") buf << c.readpartial(16384, tmp) end rescue EOFError end c.write "HTTP/1.1 201 Created\r\nConnection:close\r\n\r\n" c.close end r, w = IO.pipe fork do r.close IO.copy_stream('/dev/zero', w, nr) w.close end w.close Net::HTTP.start(addr[3], addr[1]) do |http| put = Net::HTTP::Put.new('/dev0/foo') put['Content-Type'] = 'application/content-type' put['Transfer-Encoding'] = 'chunked' put.body_stream = r puts(Benchmark.measure { http.request(put) }) end ------ * lib/net/http/generic_request.rb (write): use multi-arg write * lib/net/protocol.rb (write): support multi-arg (write0): ditto [ruby-core:84845] [Feature #14339] Modified files: trunk/lib/net/http/generic_request.rb trunk/lib/net/protocol.rb Index: lib/net/http/generic_request.rb =================================================================== --- lib/net/http/generic_request.rb (revision 61811) +++ lib/net/http/generic_request.rb (revision 61812) @@ -168,9 +168,8 @@ class Net::HTTPGenericRequest https://github.com/ruby/ruby/blob/trunk/lib/net/http/generic_request.rb#L168 def write(buf) # avoid memcpy() of buf, buf can huge and eat memory bandwidth - @sock.write("#{buf.bytesize.to_s(16)}\r\n") - rv = @sock.write(buf) - @sock.write("\r\n") + rv = buf.bytesize + @sock.write("#{rv.to_s(16)}\r\n", buf, "\r\n") rv end Index: lib/net/protocol.rb =================================================================== --- lib/net/protocol.rb (revision 61811) +++ lib/net/protocol.rb (revision 61812) @@ -209,9 +209,9 @@ module Net # :nodoc: https://github.com/ruby/ruby/blob/trunk/lib/net/protocol.rb#L209 public - def write(str) + def write(*strs) writing { - write0 str + write0 *strs } end @@ -235,9 +235,9 @@ module Net # :nodoc: https://github.com/ruby/ruby/blob/trunk/lib/net/protocol.rb#L235 bytes end - def write0(str) - @debug_output << str.dump if @debug_output - len = @io.write(str) + def write0(*strs) + @debug_output << strs.map(&:dump).join if @debug_output + len = @io.write(*strs) @written_bytes += len len end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/