yahns Ruby server user/dev discussion
 help / color / mirror / code / Atom feed
* [WIP] rely on optimized case dispatch
@ 2015-12-04 22:49 Eric Wong
  2015-12-08  5:19 ` [WIP v2] " Eric Wong
  0 siblings, 1 reply; 2+ messages in thread
From: Eric Wong @ 2015-12-04 22:49 UTC (permalink / raw)
  To: yahns-public

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


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [WIP v2] rely on optimized case dispatch
  2015-12-04 22:49 [WIP] rely on optimized case dispatch Eric Wong
@ 2015-12-08  5:19 ` Eric Wong
  0 siblings, 0 replies; 2+ messages in thread
From: Eric Wong @ 2015-12-08  5:19 UTC (permalink / raw)
  To: yahns-public

Ruby-trunk (as of r52931) optimizes 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 optimizations in ruby-trunk.

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
---
 No actual improvements in synthetic benchmarks, yet.  It'll be
 worth investigating optimizing "Ruby constant" in when cases, too.
 Additional tweak inside the :headers of http_client.rb (yahns_step)
 when checking the kgio_tryread result

 extras/proxy_pass.rb             |  2 +-
 lib/yahns/http_client.rb         | 34 +++++++++++++--------------
 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, 67 insertions(+), 69 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 @@ def req_write(buf, timeout)
         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..117300e 100644
--- a/lib/yahns/http_client.rb
+++ b/lib/yahns/http_client.rb
@@ -28,15 +28,13 @@ def step_write
     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 @@ def input_ready
   # 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 @@ def fill_body(rsize, rbuf)
   # 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
 
@@ -132,7 +130,9 @@ def yahns_step
       # continue to outer loop
     when :headers
       case rv = kgio_tryread(k.client_header_buffer_size, rbuf)
-      when String
+      when :wait_readable, :wait_writable, nil
+        return rv
+      else # String
         if @hs.add_parse(rv)
           case input = input_ready
           when :wait_readable, :wait_writable, :close then return input
@@ -142,8 +142,6 @@ def yahns_step
           end
         end
         # keep looping on kgio_tryread
-      when :wait_readable, :wait_writable, nil
-        return rv
       end while true
     when :body
       if @hs.body_eof?
@@ -234,12 +232,12 @@ def kgio_wait_readable(timeout = self.class.client_timeout)
   # 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 @@ def wbuf_maybe(wbuf, rv)
       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 @@ def http_response_write(status, headers, body)
       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 @@ def http_response_write(status, headers, body)
         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 @@ def http_response_write(status, headers, body)
         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 @@ def http_response_write(status, headers, body)
           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 @@ def do_ccc
         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 @@ def do_ccc
           else
             response_wait_write(rv) or return :close
           end
+        else # String
+          buf = rv
         end while true
       end
     end
@@ -257,8 +257,6 @@ def http_100_response(env)
                                   : "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 @@ def http_100_response(env)
       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 @@ def proxy_write(wbuf, buf, alive)
       # 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 @@ def proxy_response_start(res, tip, kcar, req_res)
     # 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 @@ def proxy_response_start(res, tip, kcar, req_res)
       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 @@ def proxy_response_start(res, tip, kcar, req_res)
         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 @@ def proxy_response_start(res, tip, kcar, req_res)
       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 @@ def proxy_response_finish(kcar, wbuf, req_res)
     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 @@ def proxy_response_finish(kcar, wbuf, req_res)
       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 @@ def proxy_response_finish(kcar, wbuf, req_res)
       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 @@ def proxy_response_finish(kcar, wbuf, req_res)
     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 @@ def trysendfile(io, offset, count)
     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 @@ def wbuf_write(c, buf)
     # 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 @@ def initialize(str, next_state)
 
   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 @@ def atfork_parent
   # 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


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-12-08  5:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-04 22:49 [WIP] rely on optimized case dispatch Eric Wong
2015-12-08  5:19 ` [WIP v2] " Eric Wong

Code repositories for project(s) associated with this inbox:

	../../../yahns.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).