From 023a85c3083bea17375f24c751af8fd97214b8ba Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Tue, 11 Mar 2008 18:09:51 +0100 Subject: [PATCH] Add rb_thread_schedule() and threaded_processing option This change should allow Ebb to work like mongrel with threaded processing or like Thin with sequential processing. There are trade off for each, thus i've made it a command line option '-S' By default Ebb will use threaded processing because it seems that is working best. But only time will tell if that is the correction thing to do. --- benchmark/server_test.rb | 17 +++++++++++------ ruby_lib/ebb.rb | 20 +++++++++++++++----- ruby_lib/ebb/runner.rb | 9 ++++++++- src/ebb_ruby.c | 13 ++++++++----- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/benchmark/server_test.rb b/benchmark/server_test.rb index d232e94..e67c063 100644 --- a/benchmark/server_test.rb +++ b/benchmark/server_test.rb @@ -92,10 +92,10 @@ def start case name when 'emongrel' @pid = fork { start_emongrel } - when /^ebb(\d*)$/ - workers = $1.to_i - workers = 1 if workers <= 0 - @pid = fork { start_ebb(workers) } + when 'ebb_threaded' + @pid = fork { start_ebb_threaded } + when 'ebb_sequential' + @pid = fork { start_ebb_sequential } when 'mongrel' @pid = fork { start_mongrel } when 'thin' @@ -116,9 +116,14 @@ def start_emongrel Rack::Handler::Mongrel.run(app, :Host => '0.0.0.0', :Port => @port.to_i) end - def start_ebb(workers = 1) + def start_ebb_threaded require File.dirname(__FILE__) + '/../ruby_lib/ebb' - server = Ebb::start_server(app, :port => @port, :workers => workers) + server = Ebb::start_server(app, :port => @port, :threaded_processing => true) + end + + def start_ebb_sequential + require File.dirname(__FILE__) + '/../ruby_lib/ebb' + server = Ebb::start_server(app, :port => @port, :threaded_processing => false) end def start_mongrel diff --git a/ruby_lib/ebb.rb b/ruby_lib/ebb.rb index 107eea4..884c543 100644 --- a/ruby_lib/ebb.rb +++ b/ruby_lib/ebb.rb @@ -9,18 +9,28 @@ module Ebb def self.start_server(app, options={}) port = (options[:port] || 4001).to_i - FFI::server_listen_on_port(port) + if options.has_key?(:threaded_processing) + threaded_processing = options[:threaded_processing] ? true : false + else + threaded_processing = true + end - puts "Ebb listening at http://0.0.0.0:#{port}/" + Client::BASE_ENV['rack.multithread'] = threaded_processing + + FFI::server_listen_on_port(port) + puts "Ebb listening at http://0.0.0.0:#{port}/ (#{threaded_processing ? 'threaded' : 'sequential'} processing)" trap('INT') { @running = false } @running = true while @running FFI::server_process_connections() while client = FFI::waiting_clients.shift - #process_client(app, client) - Thread.new(client) { |c| c.process(app) } + if threaded_processing + Thread.new(client) { |c| c.process(app) } + else + client.process(app) + end end end @@ -157,4 +167,4 @@ def each 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported' }.freeze -end \ No newline at end of file +end diff --git a/ruby_lib/ebb/runner.rb b/ruby_lib/ebb/runner.rb index a58c2a8..a1b7a79 100644 --- a/ruby_lib/ebb/runner.rb +++ b/ruby_lib/ebb/runner.rb @@ -23,7 +23,8 @@ class Runner DEFAULT_OPTIONS = { :port => 4001, :timeout => 60, - :workers => 1 + :workers => 1, + :threaded_processing => true } # Kill the process which PID is stored in +pid_file+. @@ -119,6 +120,12 @@ def get_options_from_command_line parser.on("-P", "--pid-file FILE", "File to store PID") { |f| options[:pid_file]=f } parser.on("-t", "--timeout SECONDS", "(default: #{options[:timeout]})") { |s| options[:timeout]=s } #parser.on("-w", "--workers WORKERS", "Number of worker threads (default: #{options[:workers]})") { |w| options[:workers]=w } + parser.on("-w", "-- WORKERS", "Number of worker threads (default: #{options[:workers]})") { |w| options[:workers]=w } + + parser.on("-S", "--sequential", "do not use threaded processing") do + options[:threaded_processing] = false + end + parser.separator "" parser.on_tail("-h", "--help", "Show this message") do puts parser diff --git a/src/ebb_ruby.c b/src/ebb_ruby.c index 0a42a11..545913d 100644 --- a/src/ebb_ruby.c +++ b/src/ebb_ruby.c @@ -58,14 +58,17 @@ VALUE server_process_connections(VALUE _) { ev_timer timeout; ev_timer_init (&timeout, oneshot_timeout, 0.01, 0.); - ev_timer_start (loop, &timeout); - + ev_timer_start (loop, &timeout); ev_loop(loop, EVLOOP_ONESHOT); - /* XXX: Need way to know when the loop is finished... - * should return true or false */ - ev_timer_stop(loop, &timeout); + /* Call rb_thread_schedule() proportional to the number of rb threads running */ + /* SO HACKY! Anyone have a better way to do this? */ + int i; + for(i = 0; i < EBB_MAX_CLIENTS; i++) + if(server->clients[i].in_use) + rb_thread_schedule(); + if(server->open) return Qtrue; else