railsbench 0.9.2 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +1808 -451
- data/GCPATCH +73 -0
- data/INSTALL +5 -0
- data/Manifest.txt +23 -13
- data/PROBLEMS +0 -0
- data/README +23 -7
- data/Rakefile +1 -2
- data/bin/railsbench +7 -1
- data/config/benchmarking.rb +0 -0
- data/config/benchmarks.rb +3 -2
- data/config/benchmarks.yml +0 -0
- data/images/empty.png +0 -0
- data/images/minus.png +0 -0
- data/images/plus.png +0 -0
- data/install.rb +1 -1
- data/latest_changes.txt +18 -0
- data/lib/benchmark.rb +0 -0
- data/lib/railsbench/benchmark.rb +576 -0
- data/lib/railsbench/benchmark_specs.rb +63 -63
- data/lib/railsbench/gc_info.rb +38 -3
- data/lib/railsbench/perf_info.rb +1 -1
- data/lib/railsbench/perf_utils.rb +202 -179
- data/lib/railsbench/railsbenchmark.rb +213 -55
- data/lib/railsbench/version.rb +9 -9
- data/lib/railsbench/write_headers_only.rb +15 -15
- data/postinstall.rb +0 -0
- data/ruby185gc.patch +56 -29
- data/ruby186gc.patch +564 -0
- data/ruby19gc.patch +2425 -0
- data/script/convert_raw_data_files +49 -49
- data/script/generate_benchmarks +14 -4
- data/script/perf_bench +12 -8
- data/script/perf_comp +1 -1
- data/script/perf_comp_gc +9 -1
- data/script/perf_diff +2 -2
- data/script/perf_diff_gc +2 -2
- data/script/perf_html +1 -1
- data/script/perf_plot +192 -75
- data/script/perf_plot_gc +213 -74
- data/script/perf_prof +29 -10
- data/script/perf_run +2 -2
- data/script/perf_run_gc +2 -2
- data/script/perf_table +2 -2
- data/script/perf_tex +1 -1
- data/script/perf_times +6 -6
- data/script/perf_times_gc +14 -2
- data/script/run_urls +16 -10
- data/setup.rb +0 -0
- data/test/railsbench_test.rb +0 -0
- data/test/test_helper.rb +2 -0
- metadata +77 -55
@@ -6,7 +6,7 @@ class RailsBenchmark
|
|
6
6
|
attr_accessor :http_host, :remote_addr, :server_port
|
7
7
|
attr_accessor :relative_url_root
|
8
8
|
attr_accessor :perform_caching, :cache_template_loading
|
9
|
-
attr_accessor :session_data
|
9
|
+
attr_accessor :session_data, :session_key, :cookie_data
|
10
10
|
|
11
11
|
def error_exit(msg)
|
12
12
|
STDERR.puts msg
|
@@ -18,7 +18,13 @@ class RailsBenchmark
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def relative_url_root=(value)
|
21
|
-
ActionController::
|
21
|
+
if ActionController::Base.respond_to?(:relative_url_root=)
|
22
|
+
# rails 2.3
|
23
|
+
ActionController::Base.relative_url_root = value
|
24
|
+
else
|
25
|
+
# earlier railses
|
26
|
+
ActionController::AbstractRequest.relative_url_root = value
|
27
|
+
end
|
22
28
|
@relative_url_root = value
|
23
29
|
end
|
24
30
|
|
@@ -35,24 +41,53 @@ class RailsBenchmark
|
|
35
41
|
@server_port = options[:server_port] || '80'
|
36
42
|
|
37
43
|
@session_data = options[:session_data] || {}
|
44
|
+
@session_key = options[:session_key] || '_session_id'
|
38
45
|
|
39
46
|
ENV['RAILS_ENV'] = 'benchmarking'
|
40
47
|
|
41
|
-
|
42
|
-
|
48
|
+
begin
|
49
|
+
require ENV['RAILS_ROOT'] + "/config/environment"
|
50
|
+
require 'dispatcher' # make edge rails happy
|
51
|
+
|
52
|
+
if Rails::VERSION::STRING >= "2.3"
|
53
|
+
@rack_middleware = true
|
54
|
+
require 'cgi/session'
|
55
|
+
CGI.class_eval <<-"end_eval"
|
56
|
+
def env_table
|
57
|
+
@env_table ||= ENV.to_hash
|
58
|
+
end
|
59
|
+
end_eval
|
60
|
+
else
|
61
|
+
@rack_middleware = false
|
62
|
+
end
|
43
63
|
|
44
|
-
|
64
|
+
rescue => e
|
65
|
+
$stderr.puts "failed to load application environment"
|
66
|
+
e.backtrace.each{|line| $stderr.puts line}
|
67
|
+
$stderr.puts "benchmarking aborted"
|
68
|
+
exit(-1)
|
69
|
+
end
|
70
|
+
|
71
|
+
# we don't want local error template output, which crashes anyway, when run under railsbench
|
45
72
|
ActionController::Rescue.class_eval "def local_request?; false; end"
|
46
73
|
|
47
|
-
#
|
74
|
+
# print backtrace and exit if action execution raises an exception
|
48
75
|
ActionController::Rescue.class_eval <<-"end_eval"
|
49
76
|
def rescue_action_in_public(exception)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
77
|
+
$stderr.puts "benchmarking aborted due to application error: " + exception.message
|
78
|
+
exception.backtrace.each{|line| $stderr.puts line}
|
79
|
+
$stderr.print "clearing database connections ..."
|
80
|
+
ActiveRecord::Base.send :clear_all_cached_connections! if ActiveRecord::Base.respond_to?(:clear_all_cached_connections)
|
81
|
+
ActiveRecord::Base.clear_all_connections! if ActiveRecord::Base.respond_to?(:clear_all_connections)
|
82
|
+
$stderr.puts
|
83
|
+
exit!(-1)
|
84
|
+
end
|
85
|
+
end_eval
|
86
|
+
|
87
|
+
# override rails ActiveRecord::Base#inspect to make profiles more readable
|
88
|
+
ActiveRecord::Base.class_eval <<-"end_eval"
|
89
|
+
def self.inspect
|
90
|
+
super
|
56
91
|
end
|
57
92
|
end_eval
|
58
93
|
|
@@ -68,16 +103,30 @@ class RailsBenchmark
|
|
68
103
|
exit
|
69
104
|
end
|
70
105
|
|
71
|
-
|
72
|
-
|
73
|
-
|
106
|
+
logger_module = Logger
|
107
|
+
if defined?(Log4r) && RAILS_DEFAULT_LOGGER.is_a?(Log4r::Logger)
|
108
|
+
logger_module = Logger
|
109
|
+
end
|
110
|
+
default_log_level = logger_module.const_get("ERROR")
|
111
|
+
log_level = options[:log] || default_log_level
|
112
|
+
ARGV.each do |arg|
|
113
|
+
case arg
|
114
|
+
when '-log'
|
115
|
+
log_level = default_log_level
|
116
|
+
when '-log=(nil|none)'
|
117
|
+
log_level = nil
|
118
|
+
when /-log=([a-zA-Z]*)/
|
119
|
+
log_level = logger_module.const_get($1.upcase) rescue default_log_level
|
120
|
+
end
|
121
|
+
end
|
74
122
|
|
75
123
|
if log_level
|
76
124
|
RAILS_DEFAULT_LOGGER.level = log_level
|
77
|
-
|
78
|
-
|
79
|
-
|
125
|
+
ActiveRecord::Base.logger.level = log_level
|
126
|
+
ActionController::Base.logger.level = log_level
|
127
|
+
ActionMailer::Base.logger = level = log_level if defined?(ActionMailer)
|
80
128
|
else
|
129
|
+
RAILS_DEFAULT_LOGGER.level = logger_module.const_get "FATAL"
|
81
130
|
ActiveRecord::Base.logger = nil
|
82
131
|
ActionController::Base.logger = nil
|
83
132
|
ActionMailer::Base.logger = nil if defined?(ActionMailer)
|
@@ -90,10 +139,12 @@ class RailsBenchmark
|
|
90
139
|
ActionController::Base.perform_caching = true if ARGV.include?('-cache')
|
91
140
|
end
|
92
141
|
|
93
|
-
if
|
94
|
-
|
95
|
-
|
96
|
-
|
142
|
+
if ActionView::Base.respond_to?(:cache_template_loading)
|
143
|
+
if options.has_key?(:cache_template_loading)
|
144
|
+
ActionView::Base.cache_template_loading = options[:cache_template_loading]
|
145
|
+
else
|
146
|
+
ActionView::Base.cache_template_loading = true
|
147
|
+
end
|
97
148
|
end
|
98
149
|
|
99
150
|
self.relative_url_root = options[:relative_url_root] || ''
|
@@ -107,25 +158,58 @@ class RailsBenchmark
|
|
107
158
|
end
|
108
159
|
|
109
160
|
def establish_test_session
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
161
|
+
if @rack_middleware
|
162
|
+
session_options = ActionController::Base.session_options
|
163
|
+
@session_id = ActiveSupport::SecureRandom.hex(16)
|
164
|
+
do_not_do_much = lambda do |env|
|
165
|
+
env["rack.session"] = @session_data
|
166
|
+
env["rack.session.options"] = {:id => @session_id}
|
167
|
+
[200, {}, ""]
|
168
|
+
end
|
169
|
+
@session_store = ActionController::Base.session_store.new(do_not_do_much, session_options)
|
170
|
+
@session_store.call({})
|
171
|
+
else
|
172
|
+
session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.stringify_keys
|
173
|
+
session_options = session_options.merge('new_session' => true)
|
174
|
+
@session = CGI::Session.new(Hash.new, session_options)
|
175
|
+
@session_data.each{ |k,v| @session[k] = v }
|
176
|
+
@session.update
|
177
|
+
@session_id = @session.session_id
|
178
|
+
end
|
116
179
|
end
|
117
180
|
|
118
181
|
def update_test_session_data(session_data)
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
182
|
+
if @rack_middleware
|
183
|
+
session_options = ActionController::Base.session_options
|
184
|
+
merge_url_specific_session_data = lambda do |env|
|
185
|
+
old_session_data = env["rack.session"]
|
186
|
+
# $stderr.puts "data in old session: #{old_session_data.inspect}"
|
187
|
+
new_session_data = old_session_data.merge(session_data || {})
|
188
|
+
# $stderr.puts "data in new session: #{new_session_data.inspect}"
|
189
|
+
env["rack.session"] = new_session_data
|
190
|
+
[200, {}, ""]
|
191
|
+
end
|
192
|
+
@session_store.instance_eval { @app = merge_url_specific_session_data }
|
193
|
+
env = {}
|
194
|
+
env["HTTP_COOKIE"] = cookie
|
195
|
+
# debugger
|
196
|
+
@session_store.call(env)
|
197
|
+
else
|
198
|
+
dbman = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager]
|
199
|
+
old_session_data = dbman.new(@session).restore
|
200
|
+
# $stderr.puts old_session_data.inspect
|
201
|
+
new_session_data = old_session_data.merge(session_data || {})
|
202
|
+
new_session_data.each{ |k,v| @session[k] = v }
|
203
|
+
@session.update
|
204
|
+
end
|
124
205
|
end
|
125
206
|
|
126
207
|
def delete_test_session
|
127
|
-
|
128
|
-
@session
|
208
|
+
# no way to delete a session by going through the session adpater in rails 2.3
|
209
|
+
if @session
|
210
|
+
@session.delete
|
211
|
+
@session = nil
|
212
|
+
end
|
129
213
|
end
|
130
214
|
|
131
215
|
# can be redefined in subclasses to clean out test sessions
|
@@ -133,6 +217,7 @@ class RailsBenchmark
|
|
133
217
|
end
|
134
218
|
|
135
219
|
def setup_test_urls(name)
|
220
|
+
@benchmark = name
|
136
221
|
@urls = BenchmarkSpec.load(name)
|
137
222
|
end
|
138
223
|
|
@@ -143,22 +228,34 @@ class RailsBenchmark
|
|
143
228
|
end
|
144
229
|
|
145
230
|
def setup_request_env(entry)
|
231
|
+
# $stderr.puts entry.inspect
|
146
232
|
ENV['REQUEST_URI'] = @relative_url_root + entry.uri
|
147
|
-
ENV
|
148
|
-
ENV
|
233
|
+
ENV.delete 'RAW_POST_DATA'
|
234
|
+
ENV.delete 'QUERY_STRING'
|
149
235
|
case ENV['REQUEST_METHOD'] = (entry.method || 'get').upcase
|
150
236
|
when 'GET'
|
151
|
-
query_data =
|
237
|
+
query_data = entry.query_string || ''
|
238
|
+
query_data = escape_data(query_data) unless entry.raw_data
|
152
239
|
ENV['QUERY_STRING'] = query_data
|
153
240
|
when 'POST'
|
154
|
-
query_data =
|
241
|
+
query_data = entry.post_data || ''
|
242
|
+
query_data = escape_data(query_data) unless entry.raw_data
|
155
243
|
ENV['RAW_POST_DATA'] = query_data
|
156
244
|
end
|
157
245
|
ENV['CONTENT_LENGTH'] = query_data.length.to_s
|
158
|
-
ENV['HTTP_COOKIE'] = entry.new_session ? '' :
|
246
|
+
ENV['HTTP_COOKIE'] = entry.new_session ? '' : cookie
|
247
|
+
ENV['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' if entry.xhr
|
248
|
+
# $stderr.puts entry.session_data.inspect
|
159
249
|
update_test_session_data(entry.session_data) unless entry.new_session
|
160
250
|
end
|
161
251
|
|
252
|
+
def before_dispatch_hook(entry)
|
253
|
+
end
|
254
|
+
|
255
|
+
def cookie
|
256
|
+
"#{@session_key}=#{@session_id}#{cookie_data}"
|
257
|
+
end
|
258
|
+
|
162
259
|
def escape_data(str)
|
163
260
|
str.split('&').map{|e| e.split('=').map{|e| CGI::escape e}.join('=')}.join('&')
|
164
261
|
end
|
@@ -169,7 +266,7 @@ class RailsBenchmark
|
|
169
266
|
@urls.each do |entry|
|
170
267
|
error_exit "No uri given for benchmark entry: #{entry.inspect}" unless entry.uri
|
171
268
|
setup_request_env(entry)
|
172
|
-
Dispatcher.dispatch
|
269
|
+
Dispatcher.dispatch(CGI.new)
|
173
270
|
end
|
174
271
|
end
|
175
272
|
|
@@ -183,7 +280,7 @@ class RailsBenchmark
|
|
183
280
|
svl = SvlRubyPV.new
|
184
281
|
elsif ARGV.include?('-svlMV')
|
185
282
|
require 'svlRubyMV'
|
186
|
-
svl = SvlRubyMV
|
283
|
+
svl = SvlRubyMV
|
187
284
|
end
|
188
285
|
rescue LoadError
|
189
286
|
# SVL dll not available, do nothing
|
@@ -194,12 +291,20 @@ class RailsBenchmark
|
|
194
291
|
ARGV.each{|arg| ruby_prof=$1 if arg =~ /-ruby_prof=([^ ]*)/ }
|
195
292
|
begin
|
196
293
|
if ruby_prof
|
197
|
-
# redirect stderr
|
294
|
+
# redirect stderr (TODO: I can't remember why we don't do this later)
|
198
295
|
if benchmark_file = ENV['RAILS_BENCHMARK_FILE']
|
199
296
|
$stderr = File.open(benchmark_file, "w")
|
200
297
|
end
|
201
298
|
require 'ruby-prof'
|
202
|
-
|
299
|
+
measure_mode = "WALL_TIME"
|
300
|
+
ARGV.each{|arg| measure_mode=$1.upcase if arg =~ /-measure_mode=([^ ]*)/ }
|
301
|
+
if %w(PROCESS_TIME WALL_TIME CPU_TIME ALLOCATIONS MEMORY).include?(measure_mode)
|
302
|
+
RubyProf.measure_mode = RubyProf.const_get measure_mode
|
303
|
+
else
|
304
|
+
$stderr = STDERR
|
305
|
+
$stderr.puts "unsupported ruby_prof measure mode: #{measure_mode}"
|
306
|
+
exit(-1)
|
307
|
+
end
|
203
308
|
RubyProf.start
|
204
309
|
end
|
205
310
|
rescue LoadError
|
@@ -230,14 +335,61 @@ class RailsBenchmark
|
|
230
335
|
GC.log "number of requests processed: #{@urls.size * iterations}"
|
231
336
|
end
|
232
337
|
|
338
|
+
# try to detect Ruby interpreter memory leaks (OS X)
|
339
|
+
if ARGV.include?('-leaks')
|
340
|
+
leaks_log = "#{ENV['RAILS_PERF_DATA']}/leaks.log"
|
341
|
+
leaks_command = "leaks -nocontext #{$$} >#{leaks_log}"
|
342
|
+
ENV.delete 'MallocStackLogging'
|
343
|
+
# $stderr.puts "executing '#{leaks_command}'"
|
344
|
+
raise "could not execute leaks command" unless system(leaks_command)
|
345
|
+
mallocs, leaks = *`head -n 2 #{leaks_log}`.split("\n").map{|l| l.gsub(/Process #{$$}: /, '')}
|
346
|
+
if mem_leaks = (leaks =~ /(\d+) leaks for (\d+) total leaked bytes/)
|
347
|
+
$stderr.puts "\n!!!!! memory leaks detected !!!!! (#{leaks_log})"
|
348
|
+
$stderr.puts "=" * leaks.length
|
349
|
+
end
|
350
|
+
if gc_stats
|
351
|
+
GC.log mallocs
|
352
|
+
GC.log leaks
|
353
|
+
end
|
354
|
+
$stderr.puts mallocs, leaks
|
355
|
+
$stderr.puts "=" * leaks.length if mem_leaks
|
356
|
+
end
|
357
|
+
|
233
358
|
# stop data collection if necessary
|
234
359
|
svl.stopDataCollection if svl
|
235
360
|
|
236
361
|
if defined? RubyProf
|
362
|
+
GC.disable #ruby-pof 0.7.x crash workaround
|
237
363
|
result = RubyProf.stop
|
238
|
-
#
|
239
|
-
|
240
|
-
|
364
|
+
GC.enable #ruby-pof 0.7.x crash workaround
|
365
|
+
min_percent = ruby_prof.split('/')[0].to_f rescue 0.1
|
366
|
+
threshold = ruby_prof.split('/')[1].to_f rescue 1.0
|
367
|
+
profile_type = nil
|
368
|
+
ARGV.each{|arg| profile_type=$1 if arg =~ /-profile_type=([^ ]*)/ }
|
369
|
+
profile_type ||= 'stack'
|
370
|
+
printer =
|
371
|
+
case profile_type
|
372
|
+
when 'stack' then RubyProf::CallStackPrinter
|
373
|
+
when 'grind' then RubyProf::CallTreePrinter
|
374
|
+
when 'flat' then RubyProf::FlatPrinter
|
375
|
+
when 'graph' then RubyProf::GraphHtmlPrinter
|
376
|
+
when 'multi' then RubyProf::MultiPrinter
|
377
|
+
else raise "unknown profile type: #{profile_type}"
|
378
|
+
end.new(result)
|
379
|
+
if profile_type == 'multi'
|
380
|
+
raise "you must specify a benchmark file when using multi printer" unless $stderr.is_a?(File)
|
381
|
+
$stderr.close
|
382
|
+
$stderr = STDERR
|
383
|
+
file_name = ENV['RAILS_BENCHMARK_FILE']
|
384
|
+
profile_name = File.basename(file_name).sub('.html','').sub(".#{profile_type}",'')
|
385
|
+
printer.print(:path => File.dirname(file_name),
|
386
|
+
:profile => profile_name,
|
387
|
+
:min_percent => min_percent, :threshold => threshold,
|
388
|
+
:title => "call tree/graph for benchmark #{@benchmark}")
|
389
|
+
else
|
390
|
+
printer.print($stderr, :min_percent => min_percent, :threshold => threshold,
|
391
|
+
:title => "call tree for benchmark #{@benchmark}")
|
392
|
+
end
|
241
393
|
end
|
242
394
|
|
243
395
|
delete_test_session
|
@@ -273,7 +425,8 @@ class RailsBenchmark
|
|
273
425
|
GC.enable; GC.start; GC.disable
|
274
426
|
request_count = 0
|
275
427
|
n.times do
|
276
|
-
|
428
|
+
before_dispatch_hook(entry)
|
429
|
+
Dispatcher.dispatch(CGI.new)
|
277
430
|
if (request_count += 1) == gc_frequency
|
278
431
|
GC.enable; GC.start; GC.disable
|
279
432
|
request_count = 0
|
@@ -286,7 +439,8 @@ class RailsBenchmark
|
|
286
439
|
urls.each do |entry|
|
287
440
|
setup_request_env(entry)
|
288
441
|
n.times do
|
289
|
-
|
442
|
+
before_dispatch_hook(entry)
|
443
|
+
Dispatcher.dispatch(CGI.new)
|
290
444
|
end
|
291
445
|
end
|
292
446
|
end
|
@@ -302,7 +456,8 @@ class RailsBenchmark
|
|
302
456
|
GC.enable; GC.start; GC.disable
|
303
457
|
GC.enable_stats if gc_stats
|
304
458
|
n.times do
|
305
|
-
|
459
|
+
before_dispatch_hook(entry)
|
460
|
+
Dispatcher.dispatch(CGI.new)
|
306
461
|
if (request_count += 1) == gc_freq
|
307
462
|
GC.enable; GC.start; GC.disable
|
308
463
|
request_count = 0
|
@@ -327,7 +482,8 @@ class RailsBenchmark
|
|
327
482
|
GC.enable_stats if gc_stats
|
328
483
|
test.report(entry.name) do
|
329
484
|
n.times do
|
330
|
-
|
485
|
+
before_dispatch_hook(entry)
|
486
|
+
Dispatcher.dispatch(CGI.new)
|
331
487
|
end
|
332
488
|
end
|
333
489
|
end
|
@@ -348,7 +504,8 @@ class RailsBenchmark
|
|
348
504
|
n.times do
|
349
505
|
urls.each do |entry|
|
350
506
|
setup_request_env(entry)
|
351
|
-
|
507
|
+
before_dispatch_hook(entry)
|
508
|
+
Dispatcher.dispatch(CGI.new)
|
352
509
|
end
|
353
510
|
end
|
354
511
|
end
|
@@ -370,7 +527,8 @@ class RailsBenchmark
|
|
370
527
|
n.times do
|
371
528
|
urls.each do |entry|
|
372
529
|
setup_request_env(entry)
|
373
|
-
|
530
|
+
before_dispatch_hook(entry)
|
531
|
+
Dispatcher.dispatch(CGI.new)
|
374
532
|
if (request_count += 1) == gc_frequency
|
375
533
|
GC.enable; GC.start; GC.disable
|
376
534
|
request_count = 0
|
@@ -391,7 +549,7 @@ class RailsBenchmarkWithActiveRecordStore < RailsBenchmark
|
|
391
549
|
|
392
550
|
def initialize(options={})
|
393
551
|
super(options)
|
394
|
-
@session_class = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager].session_class rescue CGI::Session::ActiveRecordStore
|
552
|
+
@session_class = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager].session_class rescue CGI::Session::ActiveRecordStore rescue ActiveRecord::SessionStore
|
395
553
|
end
|
396
554
|
|
397
555
|
def delete_new_test_sessions
|
@@ -403,7 +561,7 @@ end
|
|
403
561
|
|
404
562
|
__END__
|
405
563
|
|
406
|
-
# Copyright (C) 2005
|
564
|
+
# Copyright (C) 2005-2008 Stefan Kaes
|
407
565
|
#
|
408
566
|
# This program is free software; you can redistribute it and/or modify
|
409
567
|
# it under the terms of the GNU General Public License as published by
|
data/lib/railsbench/version.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
module Railsbench #:nodoc:
|
2
|
-
module VERSION #:nodoc:
|
3
|
-
MAJOR = 0
|
4
|
-
MINOR = 9
|
5
|
-
TINY =
|
6
|
-
|
7
|
-
STRING = [MAJOR, MINOR, TINY].join('.')
|
8
|
-
end
|
9
|
-
end
|
1
|
+
module Railsbench #:nodoc:
|
2
|
+
module VERSION #:nodoc:
|
3
|
+
MAJOR = 0
|
4
|
+
MINOR = 9
|
5
|
+
TINY = 8
|
6
|
+
|
7
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
8
|
+
end
|
9
|
+
end
|