Permalink
Browse files

Remove socket file when server stops.

Set back cluster to use 'thin' command to launch servers.
Add outputing benchmark results to graph using Gruff.
Bump to v0.6.1
  • Loading branch information...
1 parent 38b7c0d commit 488564f0f113991d021c9166c85c5fe747a54eb2 @macournoyer macournoyer committed Jan 26, 2008
Showing with 65 additions and 24 deletions.
  1. +4 −0 CHANGELOG
  2. +2 −1 benchmark/simple.rb
  3. +32 −8 benchmark/utils.rb
  4. +1 −1 lib/thin/cluster.rb
  5. +14 −7 lib/thin/server.rb
  6. +2 −2 lib/thin/version.rb
  7. +10 −5 spec/server_spec.rb
View
@@ -1,3 +1,7 @@
+== 0.6.1 Cheesecake release
+ * Remove socket file when server stops.
+ * Set back cluster to use 'thin' command to launch servers.
+
== 0.6.0 Big Pony release
* Add support for connection through UNIX domain socket.
Use the --socket (-S) option w/ the thin script to configure the socket filename.
View
@@ -9,5 +9,6 @@
require File.dirname(__FILE__) + '/utils'
request = (ARGV[0] || 1000).to_i # Number of request to send (ab -n option)
+output_type = (ARGV[1] || 'print')
-benchmark %w(WEBrick Mongrel EMongrel Thin), request
+benchmark output_type, %w(WEBrick Mongrel EMongrel Thin), request, [1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
View
@@ -1,6 +1,8 @@
require 'rack/lobster'
def run(handler_name, n=1000, c=1)
+ port = 7000
+
server = fork do
[STDOUT, STDERR].each { |o| o.reopen "/dev/null" }
@@ -22,27 +24,49 @@ def run(handler_name, n=1000, c=1)
app = Rack::Lobster.new
handler = Rack::Handler.const_get(handler_name)
- handler.run app, :Host => '0.0.0.0', :Port => 7000
+ handler.run app, :Host => '0.0.0.0', :Port => port
end
sleep 2
- out = `nice -n20 ab -c #{c} -n #{n} http://127.0.0.1:7000/ 2> /dev/null`
+ out = `nice -n20 ab -c #{c} -n #{n} http://127.0.0.1:port/ 2> /dev/null`
Process.kill('SIGKILL', server)
Process.wait
if requests = out.match(/^Requests.+?(\d+\.\d+)/)
- failed = out.match(/^Failed requests.+?(\d+)$/)[1]
- "#{requests[1].to_s.ljust(9)} #{failed}"
+ requests[1].to_i
else
- 'ERROR'
+ 0
end
end
-def benchmark(servers, request, concurrency_levels=[1, 10, 100])
- puts 'server request concurrency req/s failures'
- puts '=' * 53
+def benchmark(type, servers, request, concurrency_levels)
+ send "#{type}_benchmark", servers, request, concurrency_levels
+end
+
+def graph_benchmark(servers, request, concurrency_levels)
+ require '/usr/local/lib/ruby/gems/1.8/gems/gruff-0.2.9/lib/gruff'
+ g = Gruff::Area.new
+ g.title = "Server benchmark"
+
+ servers.each do |server|
+ g.data(server, concurrency_levels.collect { |c| print '.'; run(server, request, c) })
+ end
+ puts
+
+ g.x_axis_label = 'Concurrency'
+ g.y_axis_label = 'Requests / sec'
+ g.labels = {}
+ concurrency_levels.each_with_index { |c, i| g.labels[i] = c.to_s }
+
+ g.write('bench.png')
+ `open bench.png`
+end
+
+def print_benchmark(servers, request, concurrency_levels)
+ puts 'server request concurrency req/s'
+ puts '=' * 42
concurrency_levels.each do |c|
servers.each do |server|
puts "#{server.ljust(8)} #{request} #{c.to_s.ljust(4)} #{run(server, request, c)}"
View
@@ -20,7 +20,7 @@ class Cluster
def initialize(options)
@options = options.merge(:daemonize => true)
@size = @options.delete(:servers)
- @script = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'thin')
+ @script = 'thin'
if socket
@options.delete(:address)
View
@@ -43,12 +43,12 @@ class Server
def initialize(host_or_socket, port=3000, app=nil, &block)
if host_or_socket.include?('/')
@socket = host_or_socket
- else
- @host = host_or_socket
- @port = port.to_i
- end
- @app = app
- @timeout = 60 # sec
+ else
+ @host = host_or_socket
+ @port = port.to_i
+ end
+ @app = app
+ @timeout = 60 # sec
@app = Rack::Builder.new(&block).to_app if block
end
@@ -59,10 +59,12 @@ def self.start(*args, &block)
# Start the server and listen for connections
def start
- raise ArgumentError, "app required" unless @app
+ raise ArgumentError, 'app required' unless @app
trap('INT') { stop }
trap('TERM') { stop! }
+
+ at_exit { remove_socket_file } if @socket
# See http://rubyeventmachine.com/pub/rdoc/files/EPOLL.html
EventMachine.epoll
@@ -83,6 +85,7 @@ def start
# Stops the server by stopping the listening loop.
def stop
EventMachine.stop_event_loop
+ remove_socket_file
rescue
warn "Error stopping : #{$!}"
end
@@ -117,5 +120,9 @@ def initialize_connection(connection)
connection.silent = @silent
connection.unix_socket = !@socket.nil?
end
+
+ def remove_socket_file
+ File.delete(@socket) if @socket && File.exist?(@socket)
+ end
end
end
View
@@ -2,10 +2,10 @@ module Thin
module VERSION #:nodoc:
MAJOR = 0
MINOR = 6
- TINY = 0
+ TINY = 1
STRING = [MAJOR, MINOR, TINY].join('.')
- CODENAME = 'Big Pony'
+ CODENAME = 'Cheesecake'
end
end
View
@@ -122,11 +122,11 @@ def post(url, params={})
app = proc do |env|
[200, { 'Content-Type' => 'text/html' }, [env.inspect]]
end
- server = Thin::Server.new('/tmp/thin_test.sock', nil, app)
- server.timeout = 3
- server.silent = true
+ @server = Thin::Server.new('/tmp/thin_test.sock', nil, app)
+ @server.timeout = 3
+ @server.silent = true
- @thread = Thread.new { server.start }
+ @thread = Thread.new { @server.start }
sleep 0.1 until @thread.status == 'sleep'
end
@@ -140,7 +140,12 @@ def post(url, params={})
it "should handle GET in less then #{get_request_time = 0.002} RubySecond" do
proc { get('/') }.should be_faster_then(get_request_time)
- end
+ end
+
+ it "should remove socket file after server stops" do
+ @server.stop
+ File.exist?('/tmp/thin_test.sock').should be_false
+ end
after do
@thread.kill

0 comments on commit 488564f

Please sign in to comment.