ry / ebb fork watch download tarball
public this repo is viewable by everyone
Description: web server
Homepage: http://ebb.rubyforge.org
Clone URL: git://github.com/ry/ebb.git
add fcgi-rack script for benchmarking
Ryan Dahl (author)
about 1 month ago
commit  cebd9c9cba0549bc78c1459f85e8ea3eb6330771
tree    d980e69a61ce022b311bf60d5db844a3d4bc3856
parent  9b659b2e0f56a35f1ab0fd1f9e4508eb9ab9adf8
...
21
22
23
24
 
 
25
26
27
...
73
74
75
76
77
78
79
80
81
82
 
...
21
22
23
 
24
25
26
27
28
...
74
75
76
 
 
 
77
78
 
79
80
0
@@ -21,7 +21,8 @@ class SimpleApp
0
   end
0
   
0
   def call(env)
0
- commands = env['PATH_INFO'].split('/')
0
+ path = env['PATH_INFO'] || env['REQUEST_URI']
0
+ commands = path.split('/')
0
     
0
     @count += 1
0
     if commands.include?('periodical_activity') and @count % 10 != 1
0
@@ -73,9 +74,6 @@ end
0
 
0
 
0
 if $0 == __FILE__
0
- require 'rubygems'
0
- require 'ruby-debug'
0
- Debugger.start
0
   require DIR + '/../ruby_lib/ebb'
0
   server = Ebb::start_server(SimpleApp.new, :port => 4001)
0
-end
0
\ No newline at end of file
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
0
@@ -0,0 +1,70 @@
0
+#!/usr/bin/env ruby
0
+
0
+require File.dirname(__FILE__) + "/server_test"
0
+# supported servers: mongrel, emongrel, ebb, thin
0
+# use another name an a already open port for anything else
0
+usage = "e.g. server_bench response_size ebb:4001 mongrel:4002 other:4003"
0
+
0
+benchmark = ARGV.shift
0
+
0
+servers = []
0
+ARGV.each do |server|
0
+ name, port = server.split(':')
0
+ servers << ServerTest.new(name, port)
0
+end
0
+
0
+trials = {
0
+ 'response_size' => [0.1,1,5,7,10,15,18,20,23,25,30,40,45,50].map { |i|
0
+ bytes = (i*1024).to_i
0
+ [i, "ab -t 3 -q -c 50 http://0.0.0.0:PORT/bytes/#{bytes}"]
0
+ },
0
+ 'wait_fib' => [1,20,40,60,80,100].map { |c|
0
+ [c, "ab -t 3 -q -c #{c} http://0.0.0.0:PORT/periodical_activity/fibonacci/15"]
0
+ },
0
+ 'wait' => [0.5,1,1.5,2,2.5,3,3.5].map { |t|
0
+ [t, "ab -t 6 -q -c 50 http://0.0.0.0:PORT/periodical_activity/wait/#{t}"]
0
+ },
0
+ 'post_size' => [0.1,1,5,7,10,15,18,20,23,25,30,35,37,40,45,50].map { |l|
0
+ size = (l * 1024).to_i
0
+ fn = "/tmp/ebb_post_trial_#{size}"
0
+ File.open(fn, 'w+') { |f| f.write("C"*size) } unless FileTest.exists?(fn)
0
+ [l, "ab -t 6 -q -c 50 -p #{fn} http://0.0.0.0:PORT/test_post_length"]
0
+ },
0
+ 'concurrency' => [1,2,5,10,20,25,30,35,40,50,75,100].map { |c|
0
+ [c, "ab -t 3 -q -c #{c} http://0.0.0.0:PORT/bytes/1"]
0
+ }
0
+}
0
+
0
+unless trials.has_key? benchmark
0
+ puts("must specify valid benchmark: #{trials.keys.join(" or ")}")
0
+ exit 1
0
+end
0
+
0
+trap('INT') { exit(1) }
0
+dumpfile = "#{benchmark}.dump"
0
+begin
0
+ results = ServerTestResults.open(dumpfile)
0
+ servers.each { |s| s.start }
0
+ sleep 4
0
+ trials[benchmark].rand_each do |x, cmd|
0
+ servers.rand_each do |server|
0
+ result = server.trial(cmd)
0
+ if result.nil?
0
+ server.kill
0
+ sleep 0.5
0
+ server.start
0
+ sleep 2
0
+ else
0
+ result[:benchmark] = benchmark
0
+ result[:input] = x
0
+ results << result
0
+ end
0
+ sleep 1
0
+ end
0
+ puts "---"
0
+ end
0
+ensure
0
+ puts "\n\nkilling servers"
0
+ servers.each { |server| server.kill }
0
+ results.write(dumpfile)
0
+end
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
49
50
51
52
53
54
55
56
57
58
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,58 +0,0 @@
0
-# supply the benchmark dump file as an argumetn to this program
0
-require 'rubygems'
0
-require 'google_chart'
0
-require 'server_test'
0
-
0
-class Array
0
- def max
0
- inject(first) { |m, i| i > m ? i : m }
0
- end
0
-
0
- def min
0
- inject(first) { |m, i| i < m ? i : m }
0
- end
0
-end
0
-
0
-
0
-
0
-colors = %w{F74343 444130 7DA478 E4AC3D 1F479E}
0
-data_x = []
0
-data_y = []
0
-results = ServerTestResults.open(ARGV[0])
0
-
0
-response_chart = GoogleChart::LineChart.new('500x300', Time.now.strftime('%Y.%m.%d'), true)
0
-servers = results.servers.sort_by do |x,y|
0
- results.data(x).map { |d| d[1] }.mean
0
-end.reverse
0
-
0
-cmap = {}
0
-results.servers.sort.each { |x| cmap[x] = colors.shift }
0
-
0
-servers.each do |server|
0
- data = results.data(server).sort
0
- data_x += data.map { |d| d[0] }
0
- data_y += data.map { |d| d[1] }
0
-end
0
-
0
-servers.each do |server|
0
- data = results.data(server).sort
0
- data.map! { |d| [d[0]-data_x.min, d[1]-data_y.min]}
0
- response_chart.data(server, data, cmap[server])
0
-end
0
-
0
-label = case results.benchmark
0
-when "response_size"
0
- "kilobytes served"
0
-when "wait_fib", "concurrency"
0
- "concurrency"
0
-when "post_size"
0
- "kilobytes uploaded"
0
-when "wait", "wait_fib"
0
- "seconds waited every 10 requests"
0
-end
0
-
0
-response_chart.axis(:y, :range => [data_y.min,data_y.max])
0
-response_chart.axis(:y, :labels => ['req/s'], :positions => [50])
0
-response_chart.axis(:x, :range => [data_x.min,data_x.max])
0
-response_chart.axis(:x, :labels => [label], :positions => [50])
0
-puts response_chart.to_url
...
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
0
@@ -0,0 +1,8 @@
0
+#!/usr/bin/env ruby
0
+require 'rubygems'
0
+require 'rack'
0
+require File.dirname(__FILE__) + '/../application'
0
+
0
+trap ('INT') { exit }
0
+puts ("Starting FastCGI server at 0.0.0.0:9001")
0
+Rack::Handler::FastCGI.run(SimpleApp.new, :Port => 9001)
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
0
@@ -0,0 +1,33 @@
0
+server.modules = ( "mod_rewrite", "mod_redirect",
0
+# "mod_alias",
0
+ "mod_access",
0
+# "mod_cml",
0
+# "mod_trigger_b4_dl",
0
+# "mod_auth",
0
+# "mod_status",
0
+# "mod_setenv",
0
+ "mod_fastcgi",
0
+ "mod_scgi",
0
+# "mod_proxy",
0
+# "mod_simple_vhost",
0
+# "mod_evhost",
0
+# "mod_userdir",
0
+# "mod_cgi",
0
+# "mod_compress",
0
+# "mod_ssi",
0
+# "mod_usertrack",
0
+# "mod_expire",
0
+# "mod_secdownload",
0
+# "mod_rrdtool",
0
+ "mod_accesslog" )
0
+server.document-root = "/tmp"
0
+server.port = 9000
0
+#proxy-core.protocol = "fastcgi"
0
+#proxy-core.backends = ( "0.0.0.0:9001" )
0
+#fastcgi.debug = 10
0
+fastcgi.server = ( "" => ("localhost" =>
0
+ ( "host" => "127.0.0.1"
0
+ , "port" => 9001
0
+ , "check-local" => "disable"
0
+ )
0
+ ))
...
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
0
@@ -0,0 +1,9 @@
0
+#!/usr/bin/env ruby
0
+require 'rubygems'
0
+require 'rack'
0
+require 'rack/handler/scgi'
0
+require File.dirname(__FILE__) + '/../application'
0
+
0
+trap ('INT') { exit }
0
+puts ("Starting SCGI server at 0.0.0.0:9001")
0
+Rack::Handler::SCGI.run(SimpleApp.new, :Port => 9001)
...
 
 
 
...
1
2
3
0
@@ -0,0 +1,3 @@
0
+#!/bin/sh
0
+/opt/lighttpd-1.4.19/sbin/lighttpd -v
0
+/opt/lighttpd-1.4.19/sbin/lighttpd -D -f ./lighttpd.conf &> /dev/null
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
49
50
51
52
53
54
55
56
57
58
59
0
@@ -0,0 +1,59 @@
0
+#!/usr/bin/env ruby
0
+# supply the benchmark dump file as an argumetn to this program
0
+require 'rubygems'
0
+require 'google_chart'
0
+require 'server_test'
0
+
0
+class Array
0
+ def max
0
+ inject(first) { |m, i| i > m ? i : m }
0
+ end
0
+
0
+ def min
0
+ inject(first) { |m, i| i < m ? i : m }
0
+ end
0
+end
0
+
0
+
0
+
0
+colors = %w{F74343 444130 7DA478 E4AC3D 1F479E}
0
+data_x = []
0
+data_y = []
0
+results = ServerTestResults.open(ARGV[0])
0
+
0
+response_chart = GoogleChart::LineChart.new('500x300', Time.now.strftime('%Y.%m.%d'), true)
0
+servers = results.servers.sort_by do |x,y|
0
+ results.data(x).map { |d| d[1] }.mean
0
+end.reverse
0
+
0
+cmap = {}
0
+results.servers.sort.each { |x| cmap[x] = colors.shift }
0
+
0
+servers.each do |server|
0
+ data = results.data(server).sort
0
+ data_x += data.map { |d| d[0] }
0
+ data_y += data.map { |d| d[1] }
0
+end
0
+
0
+servers.each do |server|
0
+ data = results.data(server).sort
0
+ data.map! { |d| [d[0]-data_x.min, d[1]-data_y.min]}
0
+ response_chart.data(server, data, cmap[server])
0
+end
0
+
0
+label = case results.benchmark
0
+when "response_size"
0
+ "kilobytes served"
0
+when "wait_fib", "concurrency"
0
+ "concurrency"
0
+when "post_size"
0
+ "kilobytes uploaded"
0
+when "wait", "wait_fib"
0
+ "seconds waited every 10 requests"
0
+end
0
+
0
+response_chart.axis(:y, :range => [data_y.min,data_y.max])
0
+response_chart.axis(:y, :labels => ['req/s'], :positions => [50])
0
+response_chart.axis(:x, :range => [data_x.min,data_x.max])
0
+response_chart.axis(:x, :labels => [label], :positions => [50])
0
+puts response_chart.to_url
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,70 +0,0 @@
0
-#!/usr/bin/env ruby
0
-
0
-require File.dirname(__FILE__) + "/server_test"
0
-# supported servers: mongrel, emongrel, ebb, thin
0
-# use another name an a already open port for anything else
0
-usage = "e.g. server_bench response_size ebb:4001 mongrel:4002 other:4003"
0
-
0
-benchmark = ARGV.shift
0
-
0
-servers = []
0
-ARGV.each do |server|
0
- name, port = server.split(':')
0
- servers << ServerTest.new(name, port)
0
-end
0
-
0
-trials = {
0
- 'response_size' => [0.1,1,5,7,10,15,18,20,23,25,30,40,45,50].map { |i|
0
- bytes = (i*1024).to_i
0
- [i, "ab -t 3 -q -c 50 http://0.0.0.0:PORT/bytes/#{bytes}"]
0
- },
0
- 'wait_fib' => [1,20,40,60,80,100].map { |c|
0
- [c, "ab -t 3 -q -c #{c} http://0.0.0.0:PORT/periodical_activity/fibonacci/15"]
0
- },
0
- 'wait' => [0.5,1,1.5,2,2.5,3,3.5].map { |t|
0
- [t, "ab -t 6 -q -c 50 http://0.0.0.0:PORT/periodical_activity/wait/#{t}"]
0
- },
0
- 'post_size' => [0.1,1,5,7,10,15,18,20,23,25,30,35,37,40,45,50].map { |l|
0
- size = (l * 1024).to_i
0
- fn = "/tmp/ebb_post_trial_#{size}"
0
- File.open(fn, 'w+') { |f| f.write("C"*size) } unless FileTest.exists?(fn)
0
- [l, "ab -t 6 -q -c 50 -p #{fn} http://0.0.0.0:PORT/test_post_length"]
0
- },
0
- 'concurrency' => [1,2,5,10,20,25,30,35,40,50,75,100].map { |c|
0
- [c, "ab -t 3 -q -c #{c} http://0.0.0.0:PORT/bytes/1"]
0
- }
0
-}
0
-
0
-unless trials.has_key? benchmark
0
- puts("must specify valid benchmark: #{trials.keys.join(" or ")}")
0
- exit 1
0
-end
0
-
0
-trap('INT') { exit(1) }
0
-dumpfile = "#{benchmark}.dump"
0
-begin
0
- results = ServerTestResults.open(dumpfile)
0
- servers.each { |s| s.start }
0
- sleep 4
0
- trials[benchmark].rand_each do |x, cmd|
0
- servers.rand_each do |server|
0
- result = server.trial(cmd)
0
- if result.nil?
0
- server.kill
0
- sleep 0.5
0
- server.start
0
- sleep 2
0
- else
0
- result[:benchmark] = benchmark
0
- result[:input] = x
0
- results << result
0
- end
0
- sleep 1
0
- end
0
- puts "---"
0
- end
0
-ensure
0
- puts "\n\nkilling servers"
0
- servers.each { |server| server.kill }
0
- results.write(dumpfile)
0
-end
...
173
174
175
 
 
 
176
177
178
...
181
182
183
184
 
 
 
185
186
187
188
 
189
190
191
...
173
174
175
176
177
178
179
180
181
...
184
185
186
 
187
188
189
190
191
192
193
194
195
196
197
0
@@ -173,6 +173,9 @@ class ServerTest
0
     
0
     return nil unless r =~ /Requests per second:\s*(\d+\.\d\d)/
0
     rps = $1.to_f
0
+ if r =~ /Time taken for tests:\s*(\d+\.\d+) seconds/
0
+ time_taken = $1.to_f
0
+ end
0
     if r =~ /Complete requests:\s*(\d+)/
0
       requests_completed = $1.to_i
0
     end
0
@@ -181,11 +184,14 @@ class ServerTest
0
     else
0
       raise "didn't get how many failed requests from ab"
0
     end
0
- puts " #{rps} req/sec (#{requests_completed} completed, #{failed_requests} failed)"
0
+ successful_requests = requests_completed - failed_requests
0
+ puts " #{rps} req/sec (#{requests_completed} total, #{failed_requests} failed in #{"%.2f" % time_taken} seconds)"
0
+ puts " #{"%.2f" % (successful_requests/time_taken)} successful req/sec"
0
     
0
     {
0
       :server => @name,
0
       :rps => rps,
0
+ :time_taken => time_taken,
0
       :requests_completed => requests_completed,
0
       :requests_failed => failed_requests,
0
       :ab_cmd => cmd
...
5
6
7
8
9
10
11
12
...
5
6
7
 
 
8
9
10
0
@@ -5,8 +5,6 @@ require 'net/http'
0
 require 'socket'
0
 require 'rubygems'
0
 require 'json'
0
-require 'ruby-debug'
0
-Debugger.start
0
 
0
 
0
 Ebb.log = File.open('/dev/null','w')

Comments

    No one has commented yet.