about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-12-27 02:43:44 +0000
committerEric Wong <normalperson@yhbt.net>2010-12-27 02:43:44 +0000
commit94b848a8f9120bce8b0abd776b1a9b7e2f4fa30d (patch)
tree672d1f677360e849bb4bf5200dc87ec266f701dc
parenta310302708faa19042282e94525544cfbb23eba5 (diff)
downloadrainbows-94b848a8f9120bce8b0abd776b1a9b7e2f4fa30d.tar.gz
This lets Rainbows! yield the current worker process
when busy in the hopes another worker will pick up the
slack.  We can also override this for the single worker
process case later if people care enough.
-rw-r--r--lib/rainbows.rb1
-rw-r--r--lib/rainbows/thread_spawn.rb12
-rw-r--r--lib/rainbows/worker_yield.rb15
-rw-r--r--lib/rainbows/writer_thread_spawn/client.rb5
4 files changed, 20 insertions, 13 deletions
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index adbc37c..1f8b252 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -113,6 +113,7 @@ module Rainbows
   autoload :StreamFile, 'rainbows/stream_file'
   autoload :HttpResponse, 'rainbows/http_response' # deprecated
   autoload :ThreadTimeout, 'rainbows/thread_timeout'
+  autoload :WorkerYield, 'rainbows/worker_yield'
 end
 
 require 'rainbows/error'
diff --git a/lib/rainbows/thread_spawn.rb b/lib/rainbows/thread_spawn.rb
index a0ccde6..9da75f1 100644
--- a/lib/rainbows/thread_spawn.rb
+++ b/lib/rainbows/thread_spawn.rb
@@ -18,6 +18,7 @@ module Rainbows
 
   module ThreadSpawn
     include Base
+    include Rainbows::WorkerYield
 
     def accept_loop(klass) #:nodoc:
       lock = Mutex.new
@@ -26,16 +27,7 @@ module Rainbows
         klass.new(l) do |l|
           begin
             if lock.synchronize { G.cur >= limit }
-              # Sleep if we're busy, another less busy worker process may
-              # take it for us if we sleep. This is gross but other options
-              # still suck because they require expensive/complicated
-              # synchronization primitives for _every_ case, not just this
-              # unlikely one.  Since this case is (or should be) uncommon,
-              # just busy wait when we have to.
-              # We don't use Thread.pass because it needlessly spins the
-              # CPU during I/O wait, CPU cycles that can be better used
-              # by other worker _processes_.
-              sleep(0.01)
+              worker_yield
             elsif c = l.kgio_accept
               klass.new(c) do |c|
                 begin
diff --git a/lib/rainbows/worker_yield.rb b/lib/rainbows/worker_yield.rb
new file mode 100644
index 0000000..ec2a289
--- /dev/null
+++ b/lib/rainbows/worker_yield.rb
@@ -0,0 +1,15 @@
+# :enddoc:
+module Rainbows::WorkerYield
+
+  # Sleep if we're busy (and let other threads run).  Another less busy
+  # worker process may take it for us if we sleep. This is gross but
+  # other options still suck because they require expensive/complicated
+  # synchronization primitives for _every_ case, not just this unlikely
+  # one.  Since this case is (or should be) uncommon, just busy wait
+  # when we have to.  We don't use Thread.pass because it needlessly
+  # spins the CPU during I/O wait, CPU cycles that can be better used by
+  # other worker _processes_.
+  def worker_yield
+    sleep(0.01)
+  end
+end
diff --git a/lib/rainbows/writer_thread_spawn/client.rb b/lib/rainbows/writer_thread_spawn/client.rb
index f9c373e..ed60f42 100644
--- a/lib/rainbows/writer_thread_spawn/client.rb
+++ b/lib/rainbows/writer_thread_spawn/client.rb
@@ -4,6 +4,7 @@
 class Rainbows::WriterThreadSpawn::Client < Struct.new(:to_io, :q, :thr)
   include Rainbows::Response
   include Rainbows::SocketProxy
+  include Rainbows::WorkerYield
 
   CUR = {} # :nodoc:
 
@@ -17,12 +18,10 @@ class Rainbows::WriterThreadSpawn::Client < Struct.new(:to_io, :q, :thr)
   end
 
   def queue_writer
-    # not using Thread.pass here because that spins the CPU during
-    # I/O wait and will eat cycles from other worker processes.
     until CUR.size < MAX
       CUR.delete_if { |t,_|
         t.alive? ? t.join(0) : true
-      }.size >= MAX and sleep(0.01)
+      }.size >= MAX and worker_yield
     end
 
     q = Queue.new