From 37a560c5d14c15a3da7f2c10c9ea3d6002b34fe1 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 28 Nov 2009 19:42:53 -0800 Subject: refactor threaded models to use blocking accept() if possible It's a tad faster for non-keepalive connections and should do better on large SMP machines with many workers AND threads. That means the ActorSpawn model in Rubinius is nothing more than ThreadSpawn underneath (for now). --- lib/rainbows/thread_pool.rb | 51 +++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'lib/rainbows/thread_pool.rb') diff --git a/lib/rainbows/thread_pool.rb b/lib/rainbows/thread_pool.rb index f398828..917b835 100644 --- a/lib/rainbows/thread_pool.rb +++ b/lib/rainbows/thread_pool.rb @@ -27,39 +27,44 @@ module Rainbows def worker_loop(worker) init_worker_process(worker) - pool = (1..worker_connections).map { new_worker_thread } + pool = (1..worker_connections).map do + Thread.new { LISTENERS.size == 1 ? sync_worker : async_worker } + end while G.alive # if any worker dies, something is serious wrong, bail pool.each do |thr| - G.tick + G.tick or break thr.join(1) and G.quit! end end join_threads(pool) end - def new_worker_thread - Thread.new { - begin - begin - # TODO: check if select() or accept() is a problem on large - # SMP systems under Ruby 1.9. Hundreds of native threads - # all working off the same socket could be a thundering herd - # problem. On the other hand, a thundering herd may not - # even incur as much overhead as an extra Mutex#synchronize - ret = IO.select(LISTENERS, nil, nil, 1) and - ret.first.each do |s| - s = Rainbows.accept(s) and process_client(s) - end - rescue Errno::EINTR - rescue Errno::EBADF, TypeError - break - end - rescue => e - Error.listen_loop(e) - end while G.alive - } + def sync_worker + s = LISTENERS.first + begin + process_client(s.accept) + rescue Errno::EINTR, Errno::ECONNABORTED + rescue => e + Error.listen_loop(e) + end while G.alive + end + + def async_worker + begin + # TODO: check if select() or accept() is a problem on large + # SMP systems under Ruby 1.9. Hundreds of native threads + # all working off the same socket could be a thundering herd + # problem. On the other hand, a thundering herd may not + # even incur as much overhead as an extra Mutex#synchronize + ret = IO.select(LISTENERS, nil, nil, 1) and ret.first.each do |s| + s = Rainbows.accept(s) and process_client(s) + end + rescue Errno::EINTR + rescue => e + Error.listen_loop(e) + end while G.alive end end -- cgit v1.2.3-24-ge0c7