ry / ebb fork watch download tarball
public
Description: web server
Homepage: http://ebb.rubyforge.org
Clone URL: git://github.com/ry/ebb.git
Search Repo:
File reorganization

Attempting to make it easier to compile and install Ebb. Including libev 
in the distribution. Gem install seems to work.
Ryan Dahl (author)
Sun Feb 17 09:42:40 -0800 2008
commit  95ddafd67a7e620a8e637c424cb7cc2b7621b74b
tree    5af45775d8c109a2663ed4dc26eee55d869b2124
parent  8e8b428d6fead26dbea463217be5d51109a877fd
...
1
2
 
3
 
 
 
 
 
 
 
4
5
6
 
 
7
8
9
10
11
12
...
11
12
13
14
15
 
 
 
16
17
18
19
20
21
 
22
23
24
25
26
27
28
29
30
31
32
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
 
14
15
16
17
18
19
20
21
...
20
21
22
 
 
23
24
25
26
 
27
 
 
 
28
29
30
31
32
33
34
 
 
 
 
 
35
36
37
0
@@ -1,9 +1,18 @@
0
 require 'rake'
0
 require 'rake/gempackagetask'
0
+require 'rake/clean'
0
 
0
+task(:package => 'src/parser.c')
0
+file('src/parser.c' => 'src/parser.rl') do
0
+ sh 'ragel src/parser.rl | rlgen-cd -G2 -o src/parser.c'
0
+end
0
+
0
+task(:wc) { sh "wc -l ruby_lib/*.rb src/ebb*.{c,h}" }
0
+
0
 spec = Gem::Specification.new do |s|
0
   s.platform = Gem::Platform::RUBY
0
- s.summary = "Web server"
0
+ s.summary = "A Web Server"
0
+ s.description = ''
0
   s.name = 'ebb'
0
   s.author = 'ry dahl'
0
   s.email = 'ry@tinyclouds.org'
0
0
0
0
@@ -11,23 +20,19 @@
0
   s.version = '0.0.1'
0
   s.requirements << 'none'
0
   
0
- s.require_path = 'ruby_binding/lib'
0
- s.extensions = 'ruby_binding/ext/extconf.rb'
0
+ s.require_path = 'ruby_lib'
0
+ s.extensions = 'src/extconf.rb'
0
+ s.bindir = 'bin'
0
   s.executables = %w(ebb_rails)
0
- s.bindir = "ruby_binding/bin"
0
   
0
- s.autorequire = 'rake'
0
- s.files = FileList.new('ruby_binding/**/*', 'src/**/*', 'README').to_a
0
- s.description = ''
0
+ s.files = ['{src,libev,benchmark,ruby_lib}/*.(rb|c|h)', 'bin/ebb_rails','README']
0
 end
0
 
0
 Rake::GemPackageTask.new(spec) do |pkg|
0
   pkg.need_zip = true
0
 end
0
 
0
-task :clean do
0
- sh 'cd src && make clean'
0
- sh 'cd ruby_binding && rake clobber'
0
- sh 'rm -rf pkg'
0
-end
0
+
0
+CLEAN.add ["**/*.{o,bundle,so,obj,pdb,lib,def,exp}", "benchmark/*.dump"]
0
+CLOBBER.add ['src/Makefile', 'src/parser.c', 'src/mkmf.log','doc', 'coverage']
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
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
71
72
0
@@ -1 +1,73 @@
0
+DIR = File.dirname(__FILE__)
0
+
0
+def fib(n)
0
+ return 1 if n <= 1
0
+ fib(n-1) + fib(n-2)
0
+end
0
+
0
+def wait(seconds)
0
+ n = (seconds / 0.01).to_i
0
+ n.times do
0
+ sleep(0.01)
0
+ #File.read(DIR + '/yahoo.html')
0
+ end
0
+end
0
+
0
+class SimpleApp
0
+ @@responses = {}
0
+
0
+ def initialize
0
+ @count = 0
0
+ end
0
+
0
+ def call(env)
0
+ commands = env['PATH_INFO'].split('/')
0
+
0
+ @count += 1
0
+ if commands.include?('periodical_activity') and @count % 10 != 1
0
+ return [200, {'Content-Type'=>'text/plain'}, "quick response!\r\n"]
0
+ end
0
+
0
+ if commands.include?('fibonacci')
0
+ n = commands.last.to_i
0
+ raise "fibonacci called with n <= 0" if n <= 0
0
+ body = (1..n).to_a.map { |i| fib(i).to_s }.join(' ')
0
+ status = 200
0
+
0
+ elsif commands.include?('wait')
0
+ n = commands.last.to_i
0
+ raise "wait called with n <= 0" if n <= 0
0
+ wait(n)
0
+ body = "waited about #{n} seconds"
0
+ status = 200
0
+
0
+ elsif commands.include?('bytes')
0
+ n = commands.last.to_i
0
+ raise "bytes called with n <= 0" if n <= 0
0
+ body = @@responses[n] || "C"*n
0
+ status = 200
0
+
0
+ elsif commands.include?('test_post_length')
0
+ input_body = ""
0
+ while chunk = env['rack.input'].read(10)
0
+ input_body << chunk
0
+ end
0
+ if env['HTTP_CONTENT_LENGTH'].to_i == input_body.length
0
+ body = "Content-Length matches input length"
0
+ status = 200
0
+ else
0
+ body = "Content-Length doesn't matches input length!
0
+ content_length = #{env['HTTP_CONTENT_LENGTH'].to_i}
0
+ input_body.length = #{input_body.length}"
0
+ status = 500
0
+ end
0
+
0
+ else
0
+ status = 404
0
+ body = "Undefined url"
0
+ end
0
+
0
+ [status, {'Content-Type' => 'text/plain'}, body + "\r\n\r\n"]
0
+ end
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
0
@@ -1 +1,29 @@
0
+#!/usr/bin/env ruby
0
+$: << File.expand_path(File.dirname(__FILE__))
0
+
0
+require 'server_test'
0
+
0
+trap('INT') { exit(1) }
0
+begin
0
+ results = ServerTestResults.open('./concurrency_results.dump')
0
+ $servers.each { |s| s.start }
0
+ sleep 3
0
+ [1,10,20,30,50,75,100].rand_each do |concurrency|
0
+ $servers.rand_each do |server|
0
+ if r = server.trial(:concurrency => concurrency)
0
+ results << r
0
+ else
0
+ puts "error! restarting server"
0
+ server.kill
0
+ server.start
0
+ end
0
+ sleep 0.2 # give the other process some time to cool down?
0
+ end
0
+ puts "---"
0
+ end
0
+ensure
0
+ puts "\n\nkilling servers"
0
+ $servers.each { |server| server.kill }
0
+ results.write('./concurrency_results.dump')
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
0
@@ -1 +1,37 @@
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 avg
0
+ sum.to_f / length
0
+ end
0
+ def sum
0
+ inject(0) { |i, s| s += i }
0
+ end
0
+end
0
+
0
+colors = %w{F74343 444130 7DA478 E4AC3D}
0
+max_x = 0
0
+max_y = 0
0
+results = ServerTestResults.open(ARGV[0] || 'concurrency_results.dump')
0
+all_m = []
0
+concurrency_chart = GoogleChart::LineChart.new('400x300',
0
+ Time.now.strftime('%Y.%m.%d, 20 kbyte responses'),
0
+ true)
0
+results.servers.each do |server|
0
+ data = results.data(server, :concurrency).sort
0
+ concurrency_chart.data(server, data, colors.shift)
0
+ # data.delete_if { |d| d[0] > 100.kilobytes }
0
+ x = data.map { |d| d[0] }.max
0
+ y = data.map { |d| d[1] }.max
0
+ max_x = x if x > max_x
0
+ max_y = y if y > max_y
0
+end
0
+concurrency_chart.axis(:y, :range => [0,max_y])
0
+concurrency_chart.axis(:y, :labels => ['req/s'], :positions => [50])
0
+concurrency_chart.axis(:x, :range => [0,max_x])
0
+concurrency_chart.axis(:x, :labels => ['concurrency'], :positions => [50])
0
+puts concurrency_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
0
@@ -1 +1,35 @@
0
+# supply the benchmark dump file as an argumetn to this program
0
+require 'rubygems'
0
+require 'google_response_chart'
0
+require 'server_test'
0
+
0
+class Array
0
+ def avg
0
+ sum.to_f / length
0
+ end
0
+ def sum
0
+ inject(0) { |i, s| s += i }
0
+ end
0
+end
0
+
0
+colors = %w{F74343 444130 7DA478 E4AC3D}
0
+max_x = 0
0
+max_y = 0
0
+results = ServerTestResults.open(ARGV[0])
0
+all_m = []
0
+response_chart = GoogleChart::LineChart.new('400x300', Time.now.strftime('%Y.%m.%d'), true)
0
+results.servers.each do |server|
0
+ data = results.data(server, :size).sort
0
+ response_chart.data(server, data, colors.shift)
0
+ # data.delete_if { |d| d[0] > 100.kilobytes }
0
+ x = data.map { |d| d[0] }.max
0
+ y = data.map { |d| d[1] }.max
0
+ max_x = x if x > max_x
0
+ max_y = y if y > max_y
0
+end
0
+response_chart.axis(:y, :range => [0,max_y])
0
+response_chart.axis(:y, :labels => ['req/s'], :positions => [50])
0
+response_chart.axis(:x, :range => [0,max_x])
0
+response_chart.axis(:x, :labels => ['bytes served'], :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
0
@@ -1 +1,32 @@
0
+#!/usr/bin/env ruby
0
+$: << File.expand_path(File.dirname(__FILE__))
0
+
0
+require 'server_test'
0
+
0
+trap('INT') { exit(1) }
0
+dumpfile = 'request_results.dump'
0
+begin
0
+ results = ServerTestResults.open(dumpfile)
0
+ $servers.each { |s| s.start }
0
+ sleep 3
0
+ [0,5,7,10,15,18,20,23,25,30,40,45,50].map { |i| i.kilobytes }.rand_each do |size|
0
+ $servers.rand_each do |server|
0
+ if r = server.post_trial(size)
0
+ results << r
0
+ else
0
+ puts "error!"
0
+ server.kill
0
+ sleep 0.5
0
+ server.start
0
+ sleep 2
0
+ end
0
+ sleep 2 # give the other process some time to cool down?
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
0
@@ -1 +1,35 @@
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 avg
0
+ sum.to_f / length
0
+ end
0
+ def sum
0
+ inject(0) { |i, s| s += i }
0
+ end
0
+end
0
+
0
+colors = %w{F74343 444130 7DA478 E4AC3D}
0
+max_x = 0
0
+max_y = 0
0
+results = ServerTestResults.open(ARGV[0] || 'request_results.dump')
0
+all_m = []
0
+response_chart = GoogleChart::LineChart.new('400x300', Time.now.strftime('%Y.%m.%d, c=10'), true)
0
+results.servers.each do |server|
0
+ data = results.data(server, :size).sort.map { |d| [d[0]/1024.0, d[1]] }
0
+ response_chart.data(server, data, colors.shift)
0
+ data.delete_if { |d| d[0] > 50 }
0
+ x = data.map { |d| d[0] }.max
0
+ y = data.map { |d| d[1] }.max
0
+ max_x = x if x > max_x
0
+ max_y = y if y > max_y
0
+end
0
+response_chart.axis(:y, :range => [0,max_y])
0
+response_chart.axis(:y, :labels => ['req/s'], :positions => [50])
0
+response_chart.axis(:x, :range => [0,max_x])
0
+response_chart.axis(:x, :labels => ['kilobytes POSTed'], :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
0
@@ -1 +1,30 @@
0
+#!/usr/bin/env ruby
0
+$: << File.expand_path(File.dirname(__FILE__))
0
+
0
+require 'server_test'
0
+
0
+trap('INT') { exit(1) }
0
+dumpfile = 'response_results.dump'
0
+begin
0
+ results = ServerTestResults.open(dumpfile)
0
+ $servers.each { |s| s.start }
0
+ sleep 3
0
+ [1,10,20,30,50,100,200].map { |i| i.kilobytes }.rand_each do |size|
0
+ $servers.rand_each do |server|
0
+ if r = server.trial(:size => size)
0
+ results << r
0
+ else
0
+ puts "error! restarting server"
0
+ server.kill
0
+ server.start
0
+ end
0
+ sleep 0.2 # give the other process some time to cool down?
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
0
@@ -1 +1,34 @@
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 avg
0
+ sum.to_f / length
0
+ end
0
+ def sum
0
+ inject(0) { |i, s| s += i }
0
+ end
0
+end
0
+
0
+colors = %w{F74343 444130 7DA478 E4AC3D}
0
+max_x = 0
0
+max_y = 0
0
+results = ServerTestResults.open(ARGV[0] || 'response_results.dump')
0
+all_m = []
0
+response_chart = GoogleChart::LineChart.new('400x300', Time.now.strftime('%Y.%m.%d, c=50'), true)
0
+results.servers.each do |server|
0
+ data = results.data(server, :size).sort.map { |d| [d[0]/1024.0, d[1]] }
0
+ response_chart.data(server, data, colors.shift)
0
+ x = data.map { |d| d[0] }.max
0
+ y = data.map { |d| d[1] }.max
0
+ max_x = x if x > max_x
0
+ max_y = y if y > max_y
0
+end
0
+response_chart.axis(:y, :range => [0,max_y])
0
+response_chart.axis(:y, :labels => ['req/s'], :positions => [50])
0
+response_chart.axis(:x, :range => [0,max_x])
0
+response_chart.axis(:x, :labels => ['kilobytes served'], :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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
0
@@ -1 +1,254 @@
0
+$: << File.expand_path(File.dirname(__FILE__) + '/..')
0
+
0
+require 'rubygems'
0
+require 'rack'
0
+require 'application'
0
+
0
+module Bytes
0
+ def bytes
0
+ self
0
+ end
0
+ alias :byte :bytes
0
+
0
+ def kilobytes
0
+ self * 1024
0
+ end
0
+ alias :kilobyte :kilobytes
0
+
0
+ def megabytes
0
+ self * 1024.kilobytes
0
+ end
0
+ alias :megabyte :megabytes
0
+
0
+ def gigabytes
0
+ self * 1024.megabytes
0
+ end
0
+ alias :gigabyte :gigabytes
0
+
0
+ def terabytes
0
+ self * 1024.gigabytes
0
+ end
0
+ alias :terabyte :terabytes
0
+
0
+ def petabytes
0
+ self * 1024.terabytes
0
+ end
0
+ alias :petabyte :petabytes
0
+
0
+ def exabytes
0
+ self * 1024.petabytes
0
+ end
0
+ alias :exabyte :exabytes
0
+
0
+end
0
+class Fixnum
0
+ include Bytes
0
+end
0
+
0
+def number_to_human_size(size, precision=1)
0
+ size = Kernel.Float(size)
0
+ case
0
+ when size.to_i == 1; "1 Byte"
0
+ when size < 1.kilobyte; "%d Bytes" % size
0
+ when size < 1.megabyte; "%.#{precision}f KB" % (size / 1.0.kilobyte)
0
+ when size < 1.gigabyte; "%.#{precision}f MB" % (size / 1.0.megabyte)
0
+ when size < 1.terabyte; "%.#{precision}f GB" % (size / 1.0.gigabyte)
0
+ else "%.#{precision}f TB" % (size / 1.0.terabyte)
0
+ end.sub(/([0-9])\.?0+ /, '\1 ' )
0
+rescue
0
+ nil
0
+end
0
+
0
+class Array
0
+ def avg
0
+ sum.to_f / length
0
+ end
0
+
0
+ def sum
0
+ inject(0) { |i, s| s += i }
0
+ end
0
+
0
+ def rand_each(&block)
0
+ sort_by{ rand }.each &block
0
+ end
0
+end
0
+
0
+class ServerTestResults
0
+ def self.open(filename)
0
+ if File.readable?(filename)
0
+ new(Marshal.load(File.read(filename)))
0
+ else
0
+ new
0
+ end
0
+ end
0
+
0
+ def initialize(results = [])
0
+ @results = results
0
+ end
0
+
0
+ def write(filename='results.dump')
0
+ puts "writing dump file to #{filename}"
0
+ File.open(filename, 'w+') do |f|
0
+ f.write Marshal.dump(@results)
0
+ end
0
+ end
0
+
0
+ def <<(r)
0
+ @results << r
0
+ end
0
+
0
+ def length
0
+ @results.length
0
+ end
0
+
0
+ def servers
0
+ @results.map {|r| r[:server] }.uniq.sort
0
+ end
0
+
0
+ def data(server, what=:size)
0
+ server_data = @results.find_all { |r| r[:server] == server }
0
+ ticks = server_data.map { |d| d[what] }.uniq
0
+ datas = []
0
+ ticks.each do |c|
0
+ measurements = server_data.find_all { |d| d[what] == c }.map { |d| d[:rps] }
0
+ datas << [c, measurements.avg]
0
+ end
0
+ datas
0
+ end
0
+
0
+end
0
+
0
+class ServerTest
0
+ attr_reader :name, :port, :app, :pid
0
+ def initialize(name, port, &start_block)
0
+ @name = name
0
+ @port = port
0
+ @start_block = start_block
0
+ end
0
+
0
+ def <=>(a)
0
+ @name <=> a.name
0
+ end
0
+
0
+ def kill
0
+ Process.kill('KILL', @pid)
0
+ end
0
+
0
+ def running?
0
+ !@pid.nil?
0
+ end
0
+
0
+ def start
0
+ puts "Starting #{name}"
0
+ @pid = fork { @start_block.call }
0
+ end
0
+
0
+ def trial(options = {})
0
+ concurrency = options[:concurrency] || 50
0
+ size = options[:size] || 20 * 1.kilobyte
0
+ requests = options[:requests] || 500
0
+
0
+ print "#{@name} (c=#{concurrency},s=#{size}) "
0
+ $stdout.flush
0
+ r = %x{ab -t 3 -q -c #{concurrency} http://0.0.0.0:#{@port}/bytes/#{size}}
0
+ # Complete requests: 1000
0
+
0
+ return nil unless r =~ /Requests per second:\s*(\d+\.\d\d)/
0
+ rps = $1.to_f
0
+ if r =~ /Complete requests:\s*(\d+)/
0
+ completed_requests = $1.to_i
0
+ end
0
+ puts "#{rps} req/sec (#{completed_requests} completed)"
0
+ {
0
+ :test => 'get',
0
+ :server=> @name,
0
+ :concurrency => concurrency,
0
+ :size => size,
0
+ :rps => rps,
0
+ :requests => requests,
0
+ :requests_completed => completed_requests,
0
+ :time => Time.now
0
+ }
0
+ end
0
+
0
+ def wait_trial(wait, concurrency = 50)
0
+
0
+ print "#{@name} (c=#{concurrency},wait=#{wait}) "
0
+ $stdout.flush
0
+ r = %x{ab -t #{wait*3} -q -c #{concurrency} http://0.0.0.0:#{@port}/periodical_activity/fibonacci/#{wait}}
0
+ # Complete requests: 1000
0
+
0
+ return nil unless r =~ /Requests per second:\s*(\d+\.\d\d)/
0
+ rps = $1.to_f
0
+ if r =~ /Complete requests:\s*(\d+)/
0
+ completed_requests = $1.to_i
0
+ end
0
+ puts "#{rps} req/sec (#{completed_requests} completed)"
0
+ {
0
+ :test => 'get',
0
+ :server=> @name,
0
+ :concurrency => concurrency,
0
+ :wait => wait,
0
+ :rps => rps,
0
+ :requests_completed => completed_requests,
0
+ :time => Time.now
0
+ }
0
+ end
0
+
0
+
0
+ def post_trial(size = 1, concurrency = 10)
0
+
0
+ print "#{@name} (c=#{concurrency},posting=#{size}) "
0
+ $stdout.flush
0
+
0
+ fn = "/tmp/ebb_post_trial_#{size}"
0
+ unless FileTest.exists?(fn)
0
+ File.open(fn, 'w+') { |f| f.write("C"*size) }
0
+ end
0
+
0
+ r = %x{ab -t 6 -q -c #{concurrency} -p #{fn} http://0.0.0.0:#{@port}/test_post_length}
0
+
0
+ return nil unless r =~ /Requests per second:\s*(\d+\.\d\d)/
0
+ rps = $1.to_f
0
+ if r =~ /Complete requests:\s*(\d+)/
0
+ completed_requests = $1.to_i
0
+ end
0
+ puts "#{rps} req/sec (#{completed_requests} completed)"
0
+ {
0
+ :test => 'camping1',
0
+ :server=> @name,
0
+ :concurrency => concurrency,
0
+ :size => size,
0
+ :rps => rps,
0
+ :requests_completed => completed_requests,
0
+ :time => Time.now
0
+ }
0
+ end
0
+
0
+end
0
+
0
+$servers = []
0
+app = SimpleApp.new
0
+$servers << ServerTest.new('evented mongrel', 4001) do
0
+ require 'mongrel'
0
+ require 'swiftcore/evented_mongrel'
0
+ ENV['EVENT'] = "1"
0
+ Rack::Handler::Mongrel.run(app, :Port => 4001)
0
+end
0
+
0
+$servers << ServerTest.new('ebb', 4002) do
0
+ require File.dirname(__FILE__) + '/../ruby_lib/ebb'
0
+ server = Ebb::Server.new(app, :port => 4002)
0
+ server.start
0
+end
0
+
0
+$servers << ServerTest.new('mongrel', 4003) do
0
+ require 'mongrel'
0
+ Rack::Handler::Mongrel.run(app, :Port => 4003)
0
+end
0
+
0
+$servers << ServerTest.new('thin', 4004) do
0
+ require 'thin'
0
+ Rack::Handler::Thin.run(app, :Port => 4004)
0
+end
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0
@@ -1 +1,22 @@
0
+$: << File.expand_path(File.dirname(__FILE__))
0
+require '../ruby_lib/ebb'
0
+require 'application'
0
+
0
+
0
+
0
+server = Ebb::Server.new(SimpleApp.new, {:Port => 4001})
0
+server.start
0
+
0
+
0
+# class EbbTest < Test::Unit::TestCase
0
+#
0
+# def get(path)
0
+# Net::HTTP.get_response(URI.parse("http://0.0.0.0:4001#{path}"))
0
+# end
0
+#
0
+# def test_get
0
+# response = get('/hello')
0
+# eval response.body
0
+# end
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
0
@@ -1 +1,30 @@
0
+#!/usr/bin/env ruby
0
+$: << File.expand_path(File.dirname(__FILE__))
0
+
0
+require 'server_test'
0
+
0
+trap('INT') { exit(1) }
0
+dumpfile = 'waiting_results.dump'
0
+begin
0
+ results = ServerTestResults.open(dumpfile)
0
+ $servers.each { |s| s.start }
0
+ sleep 3
0
+ [1,20,40,60,80,100].each do |c|
0
+ $servers.rand_each do |server|
0
+ if r = server.wait_trial(15, c)
0
+ results << r
0
+ else
0
+ puts "error! restarting server"
0
+ server.kill
0
+ server.start
0
+ end
0
+ sleep 0.2 # give the other process some time to cool down?
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
0
@@ -1 +1,37 @@
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