From 692ae11f5814e318964f90db2087bd9d11563b20 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 9 Nov 2009 02:37:26 -0800 Subject: rev_thread_spawn: make 1.9 TeeInput performance tolerable Somehow 1.8 performance blows with shorter reads in the Rack application. This may be because the Rev framework uses a default 16K IO size and our test applications may request less. --- lib/rainbows/ev_thread_core.rb | 18 +++++++----------- lib/rainbows/rev_thread_spawn.rb | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/rainbows/ev_thread_core.rb b/lib/rainbows/ev_thread_core.rb index 287b726..e132f18 100644 --- a/lib/rainbows/ev_thread_core.rb +++ b/lib/rainbows/ev_thread_core.rb @@ -17,19 +17,15 @@ module Rainbows # we pass ourselves off as a Socket to Unicorn::TeeInput and this # is the only method Unicorn::TeeInput requires from the socket def readpartial(length, buf = "") + # we must modify the original buffer if there was one length == 0 and return buf.replace("") - # try bufferred reads first - @tbuf && @tbuf.size > 0 and return buf.replace(@tbuf.read(length)) - tmp = @state.pop - diff = tmp.size - length - if diff > 0 - @tbuf ||= ::IO::Buffer.new - @tbuf.write(tmp[length, tmp.size]) - tmp = tmp[0, length] + # wait on the main loop to feed us + while @tbuf.size == 0 + @tbuf.write(@state.pop) + resume end - resume - buf.replace(tmp) + buf.replace(@tbuf.read(length)) end def app_spawn(input) @@ -69,7 +65,7 @@ module Rainbows if 0 == @hp.content_length app_spawn(HttpRequest::NULL_IO) # common case else # nil or len > 0 - @state, @tbuf = Queue.new, nil + @state, @tbuf = Queue.new, ::IO::Buffer.new app_spawn(nil) end when Queue diff --git a/lib/rainbows/rev_thread_spawn.rb b/lib/rainbows/rev_thread_spawn.rb index f0482fd..4eba6d9 100644 --- a/lib/rainbows/rev_thread_spawn.rb +++ b/lib/rainbows/rev_thread_spawn.rb @@ -18,23 +18,24 @@ module Rainbows # # Caveats: # - # * TeeInput performance is currently terrible under Ruby 1.9.1-p243 - # with few, fast clients. This appears to be due the Queue - # implementation in 1.9. + # * TeeInput performance is terrible unless you match the + # length argument of your env["rack.input"]#read calls + # so that it is equal to Rev::IO::INPUT_SIZE module RevThreadSpawn class Client < Rainbows::Rev::Client include EvThreadCore LOOP = ::Rev::Loop.default DR = Rainbows::Rev::DeferredResponse + TEE_RESUMER = ::Rev::AsyncWatcher.new def pause - @lock.synchronize { detach } + @lock.synchronize { disable if enabled? } end def resume - # we always attach to the loop belonging to the main thread - @lock.synchronize { attach(LOOP) } + @lock.synchronize { enable unless enabled? } + TEE_RESUMER.signal end def write(data) @@ -74,5 +75,11 @@ module Rainbows end include Rainbows::Rev::Core + + def init_worker_process(worker) + super + Client::TEE_RESUMER.attach(::Rev::Loop.default) + end + end end -- cgit v1.2.3-24-ge0c7