1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Release that improves performance a bit on most platforms, but dramatically on freebsd.

git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@117 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
zedshaw 2006-03-19 23:31:30 +00:00
parent ebeac4b031
commit 6634d89019
6 changed files with 77 additions and 26 deletions

View file

@ -32,7 +32,7 @@ end
setup_extension("http11", "http11") setup_extension("http11", "http11")
name="mongrel" name="mongrel"
version="0.3.11" version="0.3.12"
setup_gem(name, version) do |spec| setup_gem(name, version) do |spec|
spec.summary = "A small fast HTTP library and server that runs Rails, Camping, and Nitro apps." spec.summary = "A small fast HTTP library and server that runs Rails, Camping, and Nitro apps."

View file

@ -113,6 +113,12 @@ class Start < GemPlugin::Plugin "/commands"
File.unlink @pid_file if File.exist?(@pid_file) File.unlink @pid_file if File.exist?(@pid_file)
@restart = true @restart = true
} }
trap("INT") {
server.stop
File.unlink @pid_file if File.exist?(@pid_file)
@restart = false
}
end end
# hook up any rails specific plugins # hook up any rails specific plugins

View file

@ -142,6 +142,40 @@ module Mongrel
end end
end end
def self.escape(s)
s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
'%'+$1.unpack('H2'*$1.size).join('%').upcase
}.tr(' ', '+')
end
def self.unescape(s)
s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
[$1.delete('%')].pack('H*')
}
end
def self.query_parse(qs, d = '&;')
params = {}
(qs||'').split(/[#{d}] */n).inject(params) { |h,p|
k, v=unescape(p).split('=',2)
if cur = params[k]
if cur.class == Array
params[k] << v
else
params[k] = [cur, v]
end
else
params[k] = v
end
}
return params
end
end end
@ -292,25 +326,11 @@ module Mongrel
# try lowering it (after you've tuned your stuff of course). # try lowering it (after you've tuned your stuff of course).
def initialize(host, port, num_processors=20, timeout=120) def initialize(host, port, num_processors=20, timeout=120)
@socket = TCPServer.new(host, port) @socket = TCPServer.new(host, port)
@classifier = URIClassifier.new @classifier = URIClassifier.new
@req_queue = Queue.new
@host = host @host = host
@port = port @port = port
@processors = [] @worker_group = ThreadGroup.new
@timeout = timeout
# create the worker threads
num_processors.times do |i|
@processors << Thread.new do
parser = HttpParser.new
while client = @req_queue.deq
Timeout::timeout(timeout) do
process_client(client, parser)
parser.reset
end
end
end
end
end end
@ -320,8 +340,9 @@ module Mongrel
# the performance just does not improve. It is currently carefully constructed # the performance just does not improve. It is currently carefully constructed
# to make sure that it gets the best possible performance, but anyone who # to make sure that it gets the best possible performance, but anyone who
# thinks they can make it faster is more than welcome to take a crack at it. # thinks they can make it faster is more than welcome to take a crack at it.
def process_client(client, parser) def process_client(client)
begin begin
parser = HttpParser.new
params = {} params = {}
data = client.readpartial(Const::CHUNK_SIZE) data = client.readpartial(Const::CHUNK_SIZE)
@ -368,13 +389,22 @@ module Mongrel
# Runs the thing. It returns the thread used so you can "join" it. You can also # Runs the thing. It returns the thread used so you can "join" it. You can also
# access the HttpServer::acceptor attribute to get the thread later. # access the HttpServer::acceptor attribute to get the thread later.
def run def run
BasicSocket.do_not_reverse_lookup=true BasicSocket.do_not_reverse_lookup=true
@acceptor = Thread.new do @acceptor = Thread.new do
Thread.current[:stopped] = false Thread.current[:stopped] = false
while not Thread.current[:stopped] while not Thread.current[:stopped]
begin begin
@req_queue << @socket.accept client = @socket.accept
thread = Thread.new do
process_client(client)
end
thread.priority=1
@worker_group.add(thread)
rescue StopServer rescue StopServer
STDERR.puts "Server stopped. Exiting." STDERR.puts "Server stopped. Exiting."
@socket.close if not @socket.closed? @socket.close if not @socket.closed?
@ -387,17 +417,14 @@ module Mongrel
# now that processing is done we feed enough false onto the request queue to get # now that processing is done we feed enough false onto the request queue to get
# each processor to exit and stop processing. # each processor to exit and stop processing.
@processors.length.times { @req_queue << false }
# finally we wait until the queue is empty # finally we wait until the queue is empty
while @req_queue.length > 0 while @worker_group.list.length > 0
STDERR.puts "Shutdown waiting for #{@req_queue.length} requests" if @req_queue.length > 0 STDERR.puts "Shutdown waiting for #{@worker_group.list.length} requests" if @worker_group.list.length > 0
sleep 1 sleep 1
end end
end end
@acceptor.priority = 1
return @acceptor return @acceptor
end end

View file

@ -23,7 +23,7 @@ setup_gem(name, version) do |spec|
spec.description = spec.summary spec.description = spec.summary
spec.author="Zed A. Shaw" spec.author="Zed A. Shaw"
spec.add_dependency('gem_plugin', '>= 0.2.1') spec.add_dependency('gem_plugin', '>= 0.2.1')
spec.add_dependency('mongrel', '>= 0.2.1') spec.add_dependency('mongrel', '>= 0.3.11')
spec.files += Dir.glob("resources/**/*") spec.files += Dir.glob("resources/**/*")
end end

View file

@ -1,6 +1,9 @@
require 'test/unit' require 'test/unit'
require 'http11' require 'http11'
require 'mongrel'
require 'benchmark'
include Mongrel
class HttpParserTest < Test::Unit::TestCase class HttpParserTest < Test::Unit::TestCase
@ -34,5 +37,18 @@ class HttpParserTest < Test::Unit::TestCase
assert !parser.finished?, "Parser shouldn't be finished" assert !parser.finished?, "Parser shouldn't be finished"
assert parser.error?, "Parser SHOULD have error" assert parser.error?, "Parser SHOULD have error"
end end
def test_query_parse
puts HttpRequest.query_parse("zed=1&frank=2").inspect
puts HttpRequest.query_parse("zed=1&zed=2&zed=3&frank=11;zed=45").inspect
puts Benchmark.measure {
10000.times do |i|
g = HttpRequest.query_parse("zed=1&zed=2&zed=3&frank=11").inspect
end
}
end
end end

View file

@ -1,5 +1,6 @@
require 'test/unit' require 'test/unit'
require 'mongrel' require 'mongrel'
require 'benchmark'
include Mongrel include Mongrel
@ -40,5 +41,6 @@ class ResponseTest < Test::Unit::TestCase
assert io.length > 0, "output didn't have data" assert io.length > 0, "output didn't have data"
end end
end end