From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-2.8 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00, T_RP_MATCHES_RCVD,URIBL_BLOCKED shortcircuit=no autolearn=unavailable version=3.3.2 X-Original-To: yahns-public@yhbt.net Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 681762055A for ; Fri, 4 Dec 2015 22:49:29 +0000 (UTC) From: Eric Wong To: yahns-public@yhbt.net Subject: [WIP] rely on optimized case dispatch Date: Fri, 4 Dec 2015 22:49:29 +0000 Message-Id: <20151204224929.18014-1-e@80x24.org> List-Id: In the future, Ruby may optimize case dispatch for additional immediate values such as `nil', `true', and `false'. Rearrange our case statements (and take away some safety-checks :x) to take advantage of these (to-be-done) optimizations. Note: totally untested at the moment and the changes to Ruby have not yet landed. ref: https://bugs.ruby-lang.org/issues/11769 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/71818 http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/71825 --- extras/proxy_pass.rb | 2 +- lib/yahns/http_client.rb | 28 +++++++++++----------- lib/yahns/http_response.rb | 26 ++++++++++----------- lib/yahns/proxy_http_response.rb | 50 ++++++++++++++++++++-------------------- lib/yahns/sendfile_compat.rb | 6 ++--- lib/yahns/wbuf.rb | 4 ++-- lib/yahns/wbuf_str.rb | 4 ++-- lib/yahns/worker.rb | 10 ++++---- 8 files changed, 64 insertions(+), 66 deletions(-) diff --git a/extras/proxy_pass.rb b/extras/proxy_pass.rb index 29dd995..bfe3b8f 100644 --- a/extras/proxy_pass.rb +++ b/extras/proxy_pass.rb @@ -61,7 +61,7 @@ class ProxyPass # :nodoc: kgio_wait_writable(wait_time) when nil return - when String + else # String buf = rv end while true end diff --git a/lib/yahns/http_client.rb b/lib/yahns/http_client.rb index db53587..72cc8b4 100644 --- a/lib/yahns/http_client.rb +++ b/lib/yahns/http_client.rb @@ -28,15 +28,13 @@ class Yahns::HttpClient < Kgio::Socket # :nodoc: when :ignore # :ignore on hijack @state = :ignore return :ignore - when Yahns::StreamFile - @state = rv # continue looping when true, false # done return http_response_done(rv) when :ccc_done, :r100_done @state = rv return :wait_writable - else - raise "BUG: #{@state.inspect}#wbuf_flush returned #{rv.inspect}" + else # Yahns::StreamFile + @state = rv # continue looping end while true end @@ -79,14 +77,14 @@ class Yahns::HttpClient < Kgio::Socket # :nodoc: # returns :wait_readable/wait_writable/nil to yield back to epoll def fill_body(rsize, rbuf) case rv = kgio_tryread(rsize, rbuf) - when String - @hs.filter_body(rbuf, @hs.buf << rbuf) - @input.write(rbuf) - true # keep looping on kgio_tryread (but check body_eof? first) when :wait_readable, :wait_writable rv # have epoll/kqueue wait for more when nil # unexpected EOF @input.close # nil + else # String + @hs.filter_body(rbuf, @hs.buf << rbuf) + @input.write(rbuf) + true # keep looping on kgio_tryread (but check body_eof? first) end end @@ -94,16 +92,16 @@ class Yahns::HttpClient < Kgio::Socket # :nodoc: # returns :wait_readable/wait_writable/nil to yield back to epoll def read_trailers(rsize, rbuf) case rv = kgio_tryread(rsize, rbuf) - when String + when :wait_readable, :wait_writable + return rv # wait for more + when nil # unexpected EOF + return @input.close # nil + else # String if @hs.add_parse(rbuf) @input.rewind return true end # keep looping on kgio_tryread... - when :wait_readable, :wait_writable - return rv # wait for more - when nil # unexpected EOF - return @input.close # nil end while true end @@ -234,12 +232,12 @@ class Yahns::HttpClient < Kgio::Socket # :nodoc: # used by StreamInput (and thus TeeInput) for input_buffering {false|:lazy} def yahns_read(bytes, buf) case rv = kgio_tryread(bytes, buf) - when String, nil - return rv when :wait_readable kgio_wait_readable or raise Yahns::ClientTimeout, "waiting for read", [] when :wait_writable kgio_wait_writable or raise Yahns::ClientTimeout, "waiting for write", [] + else # String, nil + return rv end while true end diff --git a/lib/yahns/http_response.rb b/lib/yahns/http_response.rb index 99bf664..cbfcf77 100644 --- a/lib/yahns/http_response.rb +++ b/lib/yahns/http_response.rb @@ -75,11 +75,11 @@ module Yahns::HttpResponse # :nodoc: case rv = wbuf.wbuf_close(self) when :ignore # hijacked @state = rv - when Yahns::StreamFile - @state = rv - :wait_writable when true, false http_response_done(rv) + else # Yahns::StreamFile + @state = rv + :wait_writable end else @state = wbuf @@ -162,9 +162,6 @@ module Yahns::HttpResponse # :nodoc: case rv = kgio_syssend(buf, flags) when nil # all done, likely break - when String - flags = MSG_DONTWAIT - buf = rv # hope the skb grows when :wait_writable, :wait_readable if k.output_buffering alive = hijack ? hijack : alive @@ -174,6 +171,9 @@ module Yahns::HttpResponse # :nodoc: else response_wait_write(rv) or return :close end + else # String + flags = MSG_DONTWAIT + buf = rv # hope the skb grows end while true end @@ -192,8 +192,6 @@ module Yahns::HttpResponse # :nodoc: case rv = kgio_trywrite(chunk) when nil # all done, likely and good! break - when String - chunk = rv # hope the skb grows when we loop into the trywrite when :wait_writable, :wait_readable if k.output_buffering wbuf = Yahns::Wbuf.new(body, alive, k.output_buffer_tmpdir, rv) @@ -202,6 +200,8 @@ module Yahns::HttpResponse # :nodoc: else response_wait_write(rv) or return :close end + else # String + chunk = rv # hope the skb grows when we loop into the trywrite end while true end end @@ -231,8 +231,6 @@ module Yahns::HttpResponse # :nodoc: case rv = kgio_trywrite(buf) when nil break - when String - buf = rv when :wait_writable, :wait_readable if self.class.output_buffering wbuf = buf.dup @@ -241,6 +239,8 @@ module Yahns::HttpResponse # :nodoc: else response_wait_write(rv) or return :close end + else # String + buf = rv end while true end end @@ -257,8 +257,6 @@ module Yahns::HttpResponse # :nodoc: : "HTTP/1.1 100 Continue\r\n\r\n".freeze case rv = kgio_trywrite(buf) - when String - buf = rv when :wait_writable, :wait_readable if self.class.output_buffering @state = Yahns::WbufStr.new(buf, :r100_done) @@ -266,8 +264,10 @@ module Yahns::HttpResponse # :nodoc: else response_wait_write(rv) or return :close end - else + when nil return rv + else # String + buf = rv end while true end end diff --git a/lib/yahns/proxy_http_response.rb b/lib/yahns/proxy_http_response.rb index 3858456..13f8870 100644 --- a/lib/yahns/proxy_http_response.rb +++ b/lib/yahns/proxy_http_response.rb @@ -13,12 +13,12 @@ module Yahns::HttpResponse # :nodoc: # no write buffer, try to write directly to the client socket case rv = String === buf ? kgio_trywrite(buf) : kgio_trywritev(buf) when nil then return # done writing buf, likely - when String, Array # partial write, hope the skb grows - buf = rv when :wait_writable, :wait_readable wbuf = Yahns::Wbuf.new(nil, alive, self.class.output_buffer_tmpdir, rv) buf = buf.join if Array === buf break + else # String, Array # partial write, hope the skb grows + buf = rv end while true end @@ -97,12 +97,12 @@ module Yahns::HttpResponse # :nodoc: # send the headers case rv = kgio_syssend(res, flags) when nil then break # all done, likely - when String # partial write, highly unlikely - flags = MSG_DONTWAIT - res = rv # hope the skb grows when :wait_writable, :wait_readable # highly unlikely in real apps wbuf = proxy_write(nil, res, alive) break # keep buffering as much as possible + else # String # partial write, highly unlikely + flags = MSG_DONTWAIT + res = rv # hope the skb grows end while true rbuf = Thread.current[:yahns_rbuf] @@ -112,26 +112,26 @@ module Yahns::HttpResponse # :nodoc: if len = kcar.body_bytes_left case tmp = tip.shift || req_res.kgio_tryread(0x2000, rbuf) - when String - len = kcar.body_bytes_left -= tmp.size - wbuf = proxy_write(wbuf, tmp, alive) when nil # premature EOF return proxy_err_response(nil, req_res, nil, wbuf) when :wait_readable return wait_on_upstream(req_res, alive, wbuf) + else # String + len = kcar.body_bytes_left -= tmp.size + wbuf = proxy_write(wbuf, tmp, alive) end until len == 0 elsif kcar.chunked? # nasty chunked body req_res.proxy_trailers = nil # define to avoid warnings for now buf = '' case tmp = tip.shift || req_res.kgio_tryread(0x2000, rbuf) - when String - kcar.filter_body(buf, tmp) - wbuf = proxy_write(wbuf, chunk_out(buf), alive) unless buf.empty? when nil # premature EOF return proxy_err_response(nil, req_res, nil, wbuf) when :wait_readable return wait_on_upstream(req_res, alive, wbuf) + else # String + kcar.filter_body(buf, tmp) + wbuf = proxy_write(wbuf, chunk_out(buf), alive) unless buf.empty? end until kcar.body_eof? buf = tmp @@ -139,12 +139,12 @@ module Yahns::HttpResponse # :nodoc: rbuf = Thread.current[:yahns_rbuf] = '' until kcar.trailers(tlr, buf) case rv = req_res.kgio_tryread(0x2000, rbuf) - when String - buf << rv when :wait_readable return wait_on_upstream(req_res, alive, wbuf) when nil # premature EOF return proxy_err_response(nil, req_res, nil, wbuf) + else # String + buf << rv end # no loop here end wbuf = proxy_write(wbuf, trailer_out(tlr), alive) @@ -152,13 +152,13 @@ module Yahns::HttpResponse # :nodoc: else # no Content-Length or Transfer-Encoding: chunked, wait on EOF! case tmp = tip.shift || req_res.kgio_tryread(0x2000, rbuf) - when String - wbuf = proxy_write(wbuf, tmp, alive) when nil req_res.shutdown break when :wait_readable return wait_on_upstream(req_res, alive, wbuf) + else # String + wbuf = proxy_write(wbuf, tmp, alive) end while true end @@ -176,13 +176,13 @@ module Yahns::HttpResponse # :nodoc: if len = kcar.body_bytes_left case tmp = req_res.kgio_tryread(0x2000, rbuf) - when String - len = kcar.body_bytes_left -= tmp.size - wbuf.wbuf_write(self, tmp) when nil # premature EOF return proxy_err_response(nil, req_res, nil, wbuf) when :wait_readable return :wait_readable # self remains in :ignore, wait on upstream + else # String + len = kcar.body_bytes_left -= tmp.size + wbuf.wbuf_write(self, tmp) end while len != 0 elsif kcar.chunked? # nasty chunked body @@ -191,13 +191,13 @@ module Yahns::HttpResponse # :nodoc: unless req_res.proxy_trailers # are we done dechunking the main body, yet? case tmp = req_res.kgio_tryread(0x2000, rbuf) - when String - kcar.filter_body(buf, tmp) - buf.empty? or wbuf.wbuf_write(self, chunk_out(buf)) when nil # premature EOF return proxy_err_response(nil, req_res, nil, wbuf) when :wait_readable return :wait_readable # self remains in :ignore, wait on upstream + else # String + kcar.filter_body(buf, tmp) + buf.empty? or wbuf.wbuf_write(self, chunk_out(buf)) end until kcar.body_eof? req_res.proxy_trailers = [ tmp, [] ] # onto trailers! rbuf = Thread.current[:yahns_rbuf] = '' @@ -206,12 +206,12 @@ module Yahns::HttpResponse # :nodoc: buf, tlr = *req_res.proxy_trailers until kcar.trailers(tlr, buf) case rv = req_res.kgio_tryread(0x2000, rbuf) - when String - buf << rv when :wait_readable return :wait_readable when nil # premature EOF return proxy_err_response(nil, req_res, nil, wbuf) + else # String + buf << rv end # no loop here end wbuf.wbuf_write(self, trailer_out(tlr)) @@ -219,13 +219,13 @@ module Yahns::HttpResponse # :nodoc: else # no Content-Length or Transfer-Encoding: chunked, wait on EOF! case tmp = req_res.kgio_tryread(0x2000, rbuf) - when String - wbuf.wbuf_write(self, tmp) when nil req_res.shutdown break when :wait_readable return :wait_readable # self remains in :ignore, wait on upstream + else # String + wbuf.wbuf_write(self, tmp) end while true end diff --git a/lib/yahns/sendfile_compat.rb b/lib/yahns/sendfile_compat.rb index da2a9ec..6d4cc56 100644 --- a/lib/yahns/sendfile_compat.rb +++ b/lib/yahns/sendfile_compat.rb @@ -11,13 +11,13 @@ module Yahns::SendfileCompat str = io.read(count, buf) or return # nil for EOF n = 0 case rv = kgio_trywrite(str) - when String # partial write, keep trying - n += (str.size - rv.size) - str = rv when :wait_writable, :wait_readable return n > 0 ? n : rv when nil return n + str.size # yay! + else # String # partial write, keep trying + n += (str.size - rv.size) + str = rv end while true end end diff --git a/lib/yahns/wbuf.rb b/lib/yahns/wbuf.rb index 1a24aab..f857a60 100644 --- a/lib/yahns/wbuf.rb +++ b/lib/yahns/wbuf.rb @@ -50,12 +50,12 @@ class Yahns::Wbuf # :nodoc: # try to bypass the VFS layer and write directly to the socket # if we're all caught up case rv = String === buf ? c.kgio_trywrite(buf) : c.kgio_trywritev(buf) - when String, Array - buf = rv # retry in loop when nil return # yay! hopefully we don't have to buffer again when :wait_writable, :wait_readable @busy = rv + else # String, Array + buf = rv # retry in loop end until @busy @tmpio ||= Yahns::TmpIO.new(@tmpdir) diff --git a/lib/yahns/wbuf_str.rb b/lib/yahns/wbuf_str.rb index 89dfd33..a997a76 100644 --- a/lib/yahns/wbuf_str.rb +++ b/lib/yahns/wbuf_str.rb @@ -27,12 +27,12 @@ class Yahns::WbufStr # :nodoc: def wbuf_flush(client) case rv = client.kgio_trywrite(@str) - when String - @str = rv when :wait_writable, :wait_readable return rv when nil return @next + else # String + @str = rv end while true end end diff --git a/lib/yahns/worker.rb b/lib/yahns/worker.rb index d6e7364..aceaf4e 100644 --- a/lib/yahns/worker.rb +++ b/lib/yahns/worker.rb @@ -24,17 +24,17 @@ class Yahns::Worker # :nodoc: # dies unexpectedly. def yahns_step case buf = @to_io.kgio_tryread(4) - when String - # unpack the buffer and trigger the signal handler - signum = buf.unpack('l') - fake_sig(signum[0]) - # keep looping, more signals may be queued when nil # EOF: master died, but we are at a safe place to exit fake_sig(:QUIT) @to_io.close return :ignore when :wait_readable # keep waiting return :ignore + else # String + # unpack the buffer and trigger the signal handler + signum = buf.unpack('l') + fake_sig(signum[0]) + # keep looping, more signals may be queued end while true # loop, as multiple signals may be sent end -- EW