public
Description: A very fast & simple Ruby web server
Homepage: http://code.macournoyer.com/thin/
Clone URL: git://github.com/macournoyer/thin.git
Search Repo:
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
macournoyer (author)
Fri Jan 25 20:40:10 -0800 2008
commit  488564f0f113991d021c9166c85c5fe747a54eb2
tree    3d369fcb5f590e51da7b9af15171da4fa4185427
parent  38b7c0d42699fc8f40a48a08507021bab625adcb
...
 
 
 
 
1
2
3
...
1
2
3
4
5
6
7
0
@@ -1,3 +1,7 @@
0
+== 0.6.1 Cheesecake release
0
+ * Remove socket file when server stops.
0
+ * Set back cluster to use 'thin' command to launch servers.
0
+
0
 == 0.6.0 Big Pony release
0
  * Add support for connection through UNIX domain socket.
0
    Use the --socket (-S) option w/ the thin script to configure the socket filename.
...
9
10
11
 
12
13
 
...
9
10
11
12
13
 
14
0
@@ -9,6 +9,7 @@
0
 require File.dirname(__FILE__) + '/utils'
0
 
0
 request = (ARGV[0] || 1000).to_i # Number of request to send (ab -n option)
0
+output_type = (ARGV[1] || 'print')
0
 
0
-benchmark %w(WEBrick Mongrel EMongrel Thin), request
0
+benchmark output_type, %w(WEBrick Mongrel EMongrel Thin), request, [1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
...
1
2
3
 
 
4
5
6
7
8
9
10
...
22
23
24
25
 
26
27
28
29
30
 
31
32
33
34
35
36
37
 
38
39
 
40
41
42
43
44
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
47
48
...
1
2
3
4
5
6
7
8
9
10
11
12
...
24
25
26
 
27
28
29
30
31
 
32
33
34
35
36
37
 
 
38
39
 
40
41
42
43
 
 
 
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
0
@@ -1,6 +1,8 @@
0
 require 'rack/lobster'
0
 
0
 def run(handler_name, n=1000, c=1)
0
+ port = 7000
0
+
0
   server = fork do
0
     [STDOUT, STDERR].each { |o| o.reopen "/dev/null" }
0
       
0
0
0
0
0
@@ -22,27 +24,49 @@
0
     app = Rack::Lobster.new
0
     
0
     handler = Rack::Handler.const_get(handler_name)
0
- handler.run app, :Host => '0.0.0.0', :Port => 7000
0
+ handler.run app, :Host => '0.0.0.0', :Port => port
0
   end
0
 
0
   sleep 2
0
 
0
- out = `nice -n20 ab -c #{c} -n #{n} http://127.0.0.1:7000/ 2> /dev/null`
0
+ out = `nice -n20 ab -c #{c} -n #{n} http://127.0.0.1:port/ 2> /dev/null`
0
 
0
   Process.kill('SIGKILL', server)
0
   Process.wait
0
   
0
   if requests = out.match(/^Requests.+?(\d+\.\d+)/)
0
- failed = out.match(/^Failed requests.+?(\d+)$/)[1]
0
- "#{requests[1].to_s.ljust(9)} #{failed}"
0
+ requests[1].to_i
0
   else
0
- 'ERROR'
0
+ 0
0
   end
0
 end
0
 
0
-def benchmark(servers, request, concurrency_levels=[1, 10, 100])
0
- puts 'server request concurrency req/s failures'
0
- puts '=' * 53
0
+def benchmark(type, servers, request, concurrency_levels)
0
+ send "#{type}_benchmark", servers, request, concurrency_levels
0
+end
0
+
0
+def graph_benchmark(servers, request, concurrency_levels)
0
+ require '/usr/local/lib/ruby/gems/1.8/gems/gruff-0.2.9/lib/gruff'
0
+ g = Gruff::Area.new
0
+ g.title = "Server benchmark"
0
+
0
+ servers.each do |server|
0
+ g.data(server, concurrency_levels.collect { |c| print '.'; run(server, request, c) })
0
+ end
0
+ puts
0
+
0
+ g.x_axis_label = 'Concurrency'
0
+ g.y_axis_label = 'Requests / sec'
0
+ g.labels = {}
0
+ concurrency_levels.each_with_index { |c, i| g.labels[i] = c.to_s }
0
+
0
+ g.write('bench.png')
0
+ `open bench.png`
0
+end
0
+
0
+def print_benchmark(servers, request, concurrency_levels)
0
+ puts 'server request concurrency req/s'
0
+ puts '=' * 42
0
   concurrency_levels.each do |c|
0
     servers.each do |server|
0
       puts "#{server.ljust(8)} #{request} #{c.to_s.ljust(4)} #{run(server, request, c)}"
...
20
21
22
23
 
24
25
26
...
20
21
22
 
23
24
25
26
0
@@ -20,7 +20,7 @@
0
     def initialize(options)
0
       @options = options.merge(:daemonize => true)
0
       @size = @options.delete(:servers)
0
- @script = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'thin')
0
+ @script = 'thin'
0
       
0
       if socket
0
         @options.delete(:address)
...
43
44
45
46
47
48
49
50
51
 
 
 
 
 
 
52
53
54
55
...
59
60
61
62
 
63
64
65
 
 
66
67
68
...
83
84
85
 
86
87
88
...
116
117
118
 
 
 
 
119
120
121
...
43
44
45
 
 
 
 
 
 
46
47
48
49
50
51
52
53
54
55
...
59
60
61
 
62
63
64
65
66
67
68
69
70
...
85
86
87
88
89
90
91
...
119
120
121
122
123
124
125
126
127
128
0
@@ -43,12 +43,12 @@
0
     def initialize(host_or_socket, port=3000, app=nil, &block)
0
       if host_or_socket.include?('/')
0
         @socket = host_or_socket
0
- else
0
- @host = host_or_socket
0
- @port = port.to_i
0
- end
0
- @app = app
0
- @timeout = 60 # sec
0
+ else
0
+ @host = host_or_socket
0
+ @port = port.to_i
0
+ end
0
+ @app = app
0
+ @timeout = 60 # sec
0
       
0
       @app = Rack::Builder.new(&block).to_app if block
0
     end
0
0
@@ -59,10 +59,12 @@
0
     
0
     # Start the server and listen for connections
0
     def start
0
- raise ArgumentError, "app required" unless @app
0
+ raise ArgumentError, 'app required' unless @app
0
       
0
       trap('INT') { stop }
0
       trap('TERM') { stop! }
0
+
0
+ at_exit { remove_socket_file } if @socket
0
             
0
       # See http://rubyeventmachine.com/pub/rdoc/files/EPOLL.html
0
       EventMachine.epoll
0
@@ -83,6 +85,7 @@
0
     # Stops the server by stopping the listening loop.
0
     def stop
0
       EventMachine.stop_event_loop
0
+ remove_socket_file
0
     rescue
0
       warn "Error stopping : #{$!}"
0
     end
0
@@ -116,6 +119,10 @@
0
         connection.app = @app
0
         connection.silent = @silent
0
         connection.unix_socket = !@socket.nil?
0
+ end
0
+
0
+ def remove_socket_file
0
+ File.delete(@socket) if @socket && File.exist?(@socket)
0
       end
0
   end
0
 end
...
2
3
4
5
 
6
7
8
9
 
10
11
...
2
3
4
 
5
6
7
8
 
9
10
11
0
@@ -2,11 +2,11 @@
0
   module VERSION #:nodoc:
0
     MAJOR = 0
0
     MINOR = 6
0
- TINY = 0
0
+ TINY = 1
0
     
0
     STRING = [MAJOR, MINOR, TINY].join('.')
0
     
0
- CODENAME = 'Big Pony'
0
+ CODENAME = 'Cheesecake'
0
   end
0
 end
...
122
123
124
125
126
127
 
 
 
128
129
 
130
131
132
...
140
141
142
143
 
 
 
 
 
 
144
145
146
...
122
123
124
 
 
 
125
126
127
128
 
129
130
131
132
...
140
141
142
 
143
144
145
146
147
148
149
150
151
0
@@ -122,11 +122,11 @@
0
     app = proc do |env|
0
       [200, { 'Content-Type' => 'text/html' }, [env.inspect]]
0
     end
0
- server = Thin::Server.new('/tmp/thin_test.sock', nil, app)
0
- server.timeout = 3
0
- server.silent = true
0
+ @server = Thin::Server.new('/tmp/thin_test.sock', nil, app)
0
+ @server.timeout = 3
0
+ @server.silent = true
0
     
0
- @thread = Thread.new { server.start }
0
+ @thread = Thread.new { @server.start }
0
     sleep 0.1 until @thread.status == 'sleep'
0
   end
0
   
0
@@ -140,7 +140,12 @@
0
   
0
   it "should handle GET in less then #{get_request_time = 0.002} RubySecond" do
0
     proc { get('/') }.should be_faster_then(get_request_time)
0
- end
0
+ end
0
+
0
+ it "should remove socket file after server stops" do
0
+ @server.stop
0
+ File.exist?('/tmp/thin_test.sock').should be_false
0
+ end
0
   
0
   after do
0
     @thread.kill

Comments

    No one has commented yet.