activesupport 3.0.20 → 3.1.0
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 +24 -28
- data/README.rdoc +2 -2
- data/lib/active_support/backtrace_cleaner.rb +17 -12
- data/lib/active_support/buffered_logger.rb +7 -9
- data/lib/active_support/cache/file_store.rb +4 -3
- data/lib/active_support/cache/mem_cache_store.rb +10 -2
- data/lib/active_support/cache/strategy/local_cache.rb +28 -23
- data/lib/active_support/cache.rb +11 -14
- data/lib/active_support/callbacks.rb +195 -175
- data/lib/active_support/concern.rb +105 -35
- data/lib/active_support/configurable.rb +50 -8
- data/lib/active_support/core_ext/array/access.rb +2 -2
- data/lib/active_support/core_ext/array/conversions.rb +2 -2
- data/lib/active_support/core_ext/array/random_access.rb +10 -7
- data/lib/active_support/core_ext/array/uniq_by.rb +2 -3
- data/lib/active_support/core_ext/array/wrap.rb +1 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -2
- data/lib/active_support/core_ext/class/attribute.rb +15 -1
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +10 -86
- data/lib/active_support/core_ext/class/subclasses.rb +20 -34
- data/lib/active_support/core_ext/date/calculations.rb +17 -5
- data/lib/active_support/core_ext/date/conversions.rb +9 -2
- data/lib/active_support/core_ext/date_time/calculations.rb +26 -9
- data/lib/active_support/core_ext/date_time/conversions.rb +9 -9
- data/lib/active_support/core_ext/date_time/zones.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +3 -6
- data/lib/active_support/core_ext/float/rounding.rb +1 -1
- data/lib/active_support/core_ext/hash/conversions.rb +22 -34
- data/lib/active_support/core_ext/hash/deep_dup.rb +11 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +12 -0
- data/lib/active_support/core_ext/hash/keys.rb +6 -4
- data/lib/active_support/core_ext/hash/reverse_merge.rb +9 -14
- data/lib/active_support/core_ext/hash/slice.rb +3 -1
- data/lib/active_support/core_ext/hash.rb +1 -0
- data/lib/active_support/core_ext/integer/inflections.rb +7 -4
- data/lib/active_support/core_ext/kernel/reporting.rb +31 -0
- data/lib/active_support/core_ext/kernel/requires.rb +2 -0
- data/lib/active_support/core_ext/logger.rb +11 -38
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +12 -12
- data/lib/active_support/core_ext/module/attr_internal.rb +13 -6
- data/lib/active_support/core_ext/module/delegation.rb +1 -5
- data/lib/active_support/core_ext/module/remove_method.rb +7 -2
- data/lib/active_support/core_ext/numeric/time.rb +2 -0
- data/lib/active_support/core_ext/object/blank.rb +45 -12
- data/lib/active_support/core_ext/object/duplicable.rb +50 -9
- data/lib/active_support/core_ext/object/inclusion.rb +15 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -35
- data/lib/active_support/core_ext/object/to_param.rb +13 -8
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +29 -10
- data/lib/active_support/core_ext/object/with_options.rb +25 -8
- data/lib/active_support/core_ext/object.rb +1 -1
- data/lib/active_support/core_ext/range/cover.rb +3 -0
- data/lib/active_support/core_ext/range.rb +1 -0
- data/lib/active_support/core_ext/string/behavior.rb +1 -2
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/exclude.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/inflections.rb +1 -1
- data/lib/active_support/core_ext/string/inquiry.rb +13 -0
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +45 -62
- data/lib/active_support/core_ext/string.rb +1 -0
- data/lib/active_support/core_ext/time/calculations.rb +19 -16
- data/lib/active_support/core_ext/time/conversions.rb +2 -24
- data/lib/active_support/core_ext/time/zones.rb +32 -21
- data/lib/active_support/core_ext/uri.rb +8 -0
- data/lib/active_support/dependencies.rb +74 -28
- data/lib/active_support/deprecation/behaviors.rb +7 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
- data/lib/active_support/deprecation/reporting.rb +4 -0
- data/lib/active_support/deprecation.rb +2 -2
- data/lib/active_support/descendants_tracker.rb +9 -7
- data/lib/active_support/duration.rb +5 -0
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/file_watcher.rb +36 -0
- data/lib/active_support/hash_with_indifferent_access.rb +20 -8
- data/lib/active_support/i18n.rb +0 -1
- data/lib/active_support/i18n_railtie.rb +2 -2
- data/lib/active_support/inflections.rb +1 -0
- data/lib/active_support/inflector/inflections.rb +1 -1
- data/lib/active_support/inflector/methods.rb +5 -3
- data/lib/active_support/json/decoding.rb +37 -23
- data/lib/active_support/json/encoding.rb +12 -4
- data/lib/active_support/lazy_load_hooks.rb +7 -7
- data/lib/active_support/log_subscriber/test_helper.rb +5 -3
- data/lib/active_support/log_subscriber.rb +6 -6
- data/lib/active_support/message_encryptor.rb +1 -1
- data/lib/active_support/message_verifier.rb +1 -1
- data/lib/active_support/multibyte/chars.rb +5 -5
- data/lib/active_support/multibyte/unicode.rb +2 -1
- data/lib/active_support/notifications/fanout.rb +3 -3
- data/lib/active_support/notifications/instrumenter.rb +1 -1
- data/lib/active_support/notifications.rb +9 -10
- data/lib/active_support/ordered_hash.rb +23 -2
- data/lib/active_support/ordered_options.rb +37 -3
- data/lib/active_support/railtie.rb +1 -1
- data/lib/active_support/rescuable.rb +1 -0
- data/lib/active_support/secure_random.rb +3 -196
- data/lib/active_support/test_case.rb +2 -10
- data/lib/active_support/testing/assertions.rb +20 -7
- data/lib/active_support/testing/mochaing.rb +7 -0
- data/lib/active_support/testing/pending.rb +27 -23
- data/lib/active_support/testing/performance/jruby.rb +115 -0
- data/lib/active_support/testing/performance/rubinius.rb +113 -0
- data/lib/active_support/testing/performance/ruby/mri.rb +57 -0
- data/lib/active_support/testing/performance/ruby/yarv.rb +57 -0
- data/lib/active_support/testing/performance/ruby.rb +152 -0
- data/lib/active_support/testing/performance.rb +214 -322
- data/lib/active_support/testing/setup_and_teardown.rb +8 -11
- data/lib/active_support/time_with_zone.rb +6 -3
- data/lib/active_support/values/time_zone.rb +26 -8
- data/lib/active_support/version.rb +2 -2
- data/lib/active_support/whiny_nil.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +1 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +2 -1
- data/lib/active_support/xml_mini/nokogiri.rb +1 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -0
- data/lib/active_support/xml_mini/rexml.rb +1 -0
- data/lib/active_support/xml_mini.rb +8 -3
- data/lib/active_support.rb +4 -2
- metadata +70 -32
- checksums.yaml +0 -7
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -19
- data/lib/active_support/core_ext/cgi.rb +0 -1
- data/lib/active_support/core_ext/object/returning.rb +0 -43
- data/lib/active_support/json/backends/jsongem.rb +0 -47
- data/lib/active_support/json/backends/okjson.rb +0 -644
- data/lib/active_support/json/backends/yajl.rb +0 -44
- data/lib/active_support/json/backends/yaml.rb +0 -19
- data/lib/active_support/testing/default.rb +0 -9
|
@@ -1,38 +1,83 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
module
|
|
10
|
-
module
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'rails/version'
|
|
3
|
+
require 'active_support/concern'
|
|
4
|
+
require 'active_support/core_ext/class/delegating_attributes'
|
|
5
|
+
require 'active_support/core_ext/string/inflections'
|
|
6
|
+
require 'action_view/helpers/number_helper'
|
|
7
|
+
|
|
8
|
+
module ActiveSupport
|
|
9
|
+
module Testing
|
|
10
|
+
module Performance
|
|
11
|
+
extend ActiveSupport::Concern
|
|
12
|
+
|
|
13
|
+
included do
|
|
14
|
+
superclass_delegating_accessor :profile_options
|
|
15
|
+
self.profile_options = {}
|
|
16
|
+
|
|
17
|
+
if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions
|
|
18
|
+
include ForMiniTest
|
|
19
|
+
else
|
|
20
|
+
include ForClassicTestUnit
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# each implementation should define metrics and freeze the defaults
|
|
25
|
+
DEFAULTS =
|
|
26
|
+
if ARGV.include?('--benchmark') # HAX for rake test
|
|
27
|
+
{ :runs => 4,
|
|
28
|
+
:output => 'tmp/performance',
|
|
29
|
+
:benchmark => true }
|
|
30
|
+
else
|
|
31
|
+
{ :runs => 1,
|
|
32
|
+
:output => 'tmp/performance',
|
|
33
|
+
:benchmark => false }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def full_profile_options
|
|
37
|
+
DEFAULTS.merge(profile_options)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def full_test_name
|
|
41
|
+
"#{self.class.name}##{method_name}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
module ForMiniTest
|
|
45
|
+
def run(runner)
|
|
46
|
+
@runner = runner
|
|
47
|
+
|
|
48
|
+
run_warmup
|
|
49
|
+
if full_profile_options && metrics = full_profile_options[:metrics]
|
|
50
|
+
metrics.each do |metric_name|
|
|
51
|
+
if klass = Metrics[metric_name.to_sym]
|
|
52
|
+
run_profile(klass.new)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
return
|
|
30
58
|
end
|
|
31
59
|
|
|
32
|
-
def
|
|
33
|
-
|
|
60
|
+
def run_test(metric, mode)
|
|
61
|
+
result = '.'
|
|
62
|
+
begin
|
|
63
|
+
run_callbacks :setup
|
|
64
|
+
setup
|
|
65
|
+
metric.send(mode) { __send__ method_name }
|
|
66
|
+
rescue Exception => e
|
|
67
|
+
result = @runner.puke(self.class, method_name, e)
|
|
68
|
+
ensure
|
|
69
|
+
begin
|
|
70
|
+
teardown
|
|
71
|
+
run_callbacks :teardown, :enumerator => :reverse_each
|
|
72
|
+
rescue Exception => e
|
|
73
|
+
result = @runner.puke(self.class, method_name, e)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
result
|
|
34
77
|
end
|
|
78
|
+
end
|
|
35
79
|
|
|
80
|
+
module ForClassicTestUnit
|
|
36
81
|
def run(result)
|
|
37
82
|
return if method_name =~ /^default_test$/
|
|
38
83
|
|
|
@@ -40,11 +85,13 @@ begin
|
|
|
40
85
|
@_result = result
|
|
41
86
|
|
|
42
87
|
run_warmup
|
|
43
|
-
if
|
|
88
|
+
if full_profile_options && metrics = full_profile_options[:metrics]
|
|
44
89
|
metrics.each do |metric_name|
|
|
45
90
|
if klass = Metrics[metric_name.to_sym]
|
|
46
91
|
run_profile(klass.new)
|
|
47
92
|
result.add_run
|
|
93
|
+
else
|
|
94
|
+
puts '%20s: unsupported' % metric_name
|
|
48
95
|
end
|
|
49
96
|
end
|
|
50
97
|
end
|
|
@@ -57,7 +104,7 @@ begin
|
|
|
57
104
|
setup
|
|
58
105
|
metric.send(mode) { __send__ @method_name }
|
|
59
106
|
rescue ::Test::Unit::AssertionFailedError => e
|
|
60
|
-
|
|
107
|
+
add_failure(e.message, e.backtrace)
|
|
61
108
|
rescue StandardError, ScriptError => e
|
|
62
109
|
add_error(e)
|
|
63
110
|
ensure
|
|
@@ -70,356 +117,201 @@ begin
|
|
|
70
117
|
add_error(e)
|
|
71
118
|
end
|
|
72
119
|
end
|
|
120
|
+
end
|
|
73
121
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
122
|
+
protected
|
|
123
|
+
# overridden by each implementation
|
|
124
|
+
def run_gc; end
|
|
77
125
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
puts "%s (%s warmup)" % [full_test_name, time.format(time.total)]
|
|
126
|
+
def run_warmup
|
|
127
|
+
run_gc
|
|
81
128
|
|
|
82
|
-
|
|
83
|
-
|
|
129
|
+
time = Metrics::Time.new
|
|
130
|
+
run_test(time, :benchmark)
|
|
131
|
+
puts "%s (%s warmup)" % [full_test_name, time.format(time.total)]
|
|
84
132
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
performer = klass.new(self, metric)
|
|
133
|
+
run_gc
|
|
134
|
+
end
|
|
88
135
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
end
|
|
136
|
+
def run_profile(metric)
|
|
137
|
+
klass = full_profile_options[:benchmark] ? Benchmarker : Profiler
|
|
138
|
+
performer = klass.new(self, metric)
|
|
93
139
|
|
|
94
|
-
|
|
95
|
-
|
|
140
|
+
performer.run
|
|
141
|
+
puts performer.report
|
|
142
|
+
performer.record
|
|
143
|
+
end
|
|
96
144
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
145
|
+
class Performer
|
|
146
|
+
delegate :run_test, :full_profile_options, :full_test_name, :to => :@harness
|
|
147
|
+
|
|
148
|
+
def initialize(harness, metric)
|
|
149
|
+
@harness, @metric, @supported = harness, metric, false
|
|
150
|
+
end
|
|
100
151
|
|
|
101
|
-
|
|
102
|
-
|
|
152
|
+
def report
|
|
153
|
+
if @supported
|
|
154
|
+
rate = @total / full_profile_options[:runs]
|
|
103
155
|
'%20s: %s' % [@metric.name, @metric.format(rate)]
|
|
156
|
+
else
|
|
157
|
+
'%20s: unsupported' % @metric.name
|
|
104
158
|
end
|
|
105
|
-
|
|
106
|
-
protected
|
|
107
|
-
def output_filename
|
|
108
|
-
"#{profile_options[:output]}/#{full_test_name}_#{@metric.name}"
|
|
109
|
-
end
|
|
110
159
|
end
|
|
111
160
|
|
|
112
|
-
|
|
113
|
-
def
|
|
114
|
-
|
|
115
|
-
@total = @metric.total
|
|
161
|
+
protected
|
|
162
|
+
def output_filename
|
|
163
|
+
"#{full_profile_options[:output]}/#{full_test_name}_#{@metric.name}"
|
|
116
164
|
end
|
|
165
|
+
end
|
|
117
166
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
167
|
+
# overridden by each implementation
|
|
168
|
+
class Profiler < Performer
|
|
169
|
+
def time_with_block
|
|
170
|
+
before = Time.now
|
|
171
|
+
yield
|
|
172
|
+
Time.now - before
|
|
173
|
+
end
|
|
125
174
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
175
|
+
def run; end
|
|
176
|
+
def record; end
|
|
177
|
+
end
|
|
129
178
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
end
|
|
179
|
+
class Benchmarker < Performer
|
|
180
|
+
def initialize(*args)
|
|
181
|
+
super
|
|
182
|
+
@supported = @metric.respond_to?('measure')
|
|
183
|
+
end
|
|
136
184
|
|
|
137
|
-
|
|
138
|
-
|
|
185
|
+
def run
|
|
186
|
+
return unless @supported
|
|
139
187
|
|
|
140
|
-
|
|
141
|
-
|
|
188
|
+
full_profile_options[:runs].to_i.times { run_test(@metric, :benchmark) }
|
|
189
|
+
@total = @metric.total
|
|
190
|
+
end
|
|
142
191
|
|
|
143
|
-
|
|
192
|
+
def record
|
|
193
|
+
avg = @metric.total / full_profile_options[:runs].to_i
|
|
194
|
+
now = Time.now.utc.xmlschema
|
|
195
|
+
with_output_file do |file|
|
|
196
|
+
file.puts "#{avg},#{now},#{environment}"
|
|
144
197
|
end
|
|
198
|
+
end
|
|
145
199
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def with_output_file
|
|
150
|
-
fname = output_filename
|
|
151
|
-
|
|
152
|
-
if new = !File.exist?(fname)
|
|
153
|
-
FileUtils.mkdir_p(File.dirname(fname))
|
|
154
|
-
end
|
|
200
|
+
def environment
|
|
201
|
+
unless defined? @env
|
|
202
|
+
app = "#{$1}.#{$2}" if File.directory?('.git') && `git branch -v` =~ /^\* (\S+)\s+(\S+)/
|
|
155
203
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
204
|
+
rails = Rails::VERSION::STRING
|
|
205
|
+
if File.directory?('vendor/rails/.git')
|
|
206
|
+
Dir.chdir('vendor/rails') do
|
|
207
|
+
rails += ".#{$1}.#{$2}" if `git branch -v` =~ /^\* (\S+)\s+(\S+)/
|
|
159
208
|
end
|
|
160
209
|
end
|
|
161
210
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
class Profiler < Performer
|
|
168
|
-
def initialize(*args)
|
|
169
|
-
super
|
|
170
|
-
@supported = @metric.measure_mode rescue false
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
def run
|
|
174
|
-
return unless @supported
|
|
211
|
+
ruby = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
|
212
|
+
ruby += "-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}"
|
|
175
213
|
|
|
176
|
-
|
|
177
|
-
RubyProf.start
|
|
178
|
-
RubyProf.pause
|
|
179
|
-
profile_options[:runs].to_i.times { run_test(@metric, :profile) }
|
|
180
|
-
@data = RubyProf.stop
|
|
181
|
-
@total = @data.threads.values.sum(0) { |method_infos| method_infos.max.total_time }
|
|
214
|
+
@env = [app, rails, ruby, RUBY_PLATFORM] * ','
|
|
182
215
|
end
|
|
183
216
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
super
|
|
187
|
-
else
|
|
188
|
-
'%20s: unsupported' % @metric.name
|
|
189
|
-
end
|
|
190
|
-
end
|
|
217
|
+
@env
|
|
218
|
+
end
|
|
191
219
|
|
|
192
|
-
|
|
193
|
-
|
|
220
|
+
protected
|
|
221
|
+
HEADER = 'measurement,created_at,app,rails,ruby,platform'
|
|
194
222
|
|
|
195
|
-
|
|
223
|
+
def with_output_file
|
|
224
|
+
fname = output_filename
|
|
196
225
|
|
|
197
|
-
|
|
198
|
-
fname = output_filename(klass)
|
|
226
|
+
if new = !File.exist?(fname)
|
|
199
227
|
FileUtils.mkdir_p(File.dirname(fname))
|
|
200
|
-
File.open(fname, 'wb') do |file|
|
|
201
|
-
klass.new(@data).print(file, profile_options.slice(:min_percent))
|
|
202
|
-
end
|
|
203
228
|
end
|
|
204
|
-
end
|
|
205
229
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
case printer_class.name.demodulize
|
|
210
|
-
when 'FlatPrinter'; 'flat.txt'
|
|
211
|
-
when 'FlatPrinterWithLineNumbers'; 'flat_line_numbers.txt'
|
|
212
|
-
when 'GraphPrinter'; 'graph.txt'
|
|
213
|
-
when 'GraphHtmlPrinter'; 'graph.html'
|
|
214
|
-
when 'GraphYamlPrinter'; 'graph.yml'
|
|
215
|
-
when 'CallTreePrinter'; 'tree.txt'
|
|
216
|
-
when 'CallStackPrinter'; 'stack.html'
|
|
217
|
-
when 'DotPrinter'; 'graph.dot'
|
|
218
|
-
else printer_class.name.sub(/Printer$/, '').underscore
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
"#{super()}_#{suffix}"
|
|
230
|
+
File.open(fname, 'ab') do |file|
|
|
231
|
+
file.puts(HEADER) if new
|
|
232
|
+
yield file
|
|
222
233
|
end
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
module Metrics
|
|
226
|
-
def self.[](name)
|
|
227
|
-
const_get(name.to_s.camelize)
|
|
228
|
-
rescue NameError
|
|
229
|
-
nil
|
|
230
234
|
end
|
|
231
235
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
def initialize
|
|
236
|
-
@total = 0
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
def name
|
|
240
|
-
@name ||= self.class.name.demodulize.underscore
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
def measure_mode
|
|
244
|
-
self.class::Mode
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
def measure
|
|
248
|
-
0
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
def benchmark
|
|
252
|
-
with_gc_stats do
|
|
253
|
-
before = measure
|
|
254
|
-
yield
|
|
255
|
-
@total += (measure - before)
|
|
256
|
-
end
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def profile
|
|
260
|
-
RubyProf.resume
|
|
261
|
-
yield
|
|
262
|
-
ensure
|
|
263
|
-
RubyProf.pause
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
protected
|
|
267
|
-
# Ruby 1.9 with GC::Profiler
|
|
268
|
-
if defined?(GC::Profiler)
|
|
269
|
-
def with_gc_stats
|
|
270
|
-
GC::Profiler.enable
|
|
271
|
-
GC.start
|
|
272
|
-
yield
|
|
273
|
-
ensure
|
|
274
|
-
GC::Profiler.disable
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
# Ruby 1.8 + ruby-prof wrapper (enable/disable stats for Benchmarker)
|
|
278
|
-
elsif GC.respond_to?(:enable_stats)
|
|
279
|
-
def with_gc_stats
|
|
280
|
-
GC.enable_stats
|
|
281
|
-
yield
|
|
282
|
-
ensure
|
|
283
|
-
GC.disable_stats
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
else
|
|
287
|
-
def with_gc_stats
|
|
288
|
-
yield
|
|
289
|
-
end
|
|
290
|
-
end
|
|
236
|
+
def output_filename
|
|
237
|
+
"#{super}.csv"
|
|
291
238
|
end
|
|
239
|
+
end
|
|
292
240
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
241
|
+
module Metrics
|
|
242
|
+
def self.[](name)
|
|
243
|
+
const_get(name.to_s.camelize)
|
|
244
|
+
rescue NameError
|
|
245
|
+
nil
|
|
246
|
+
end
|
|
297
247
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
'%d ms' % (measurement * 1000)
|
|
301
|
-
else
|
|
302
|
-
'%.2f sec' % measurement
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
end
|
|
248
|
+
class Base
|
|
249
|
+
include ActionView::Helpers::NumberHelper
|
|
306
250
|
|
|
307
|
-
|
|
308
|
-
Mode = RubyProf::PROCESS_TIME
|
|
251
|
+
attr_reader :total
|
|
309
252
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
end
|
|
253
|
+
def initialize
|
|
254
|
+
@total = 0
|
|
313
255
|
end
|
|
314
256
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
def measure
|
|
319
|
-
RubyProf.measure_wall_time
|
|
320
|
-
end
|
|
257
|
+
def name
|
|
258
|
+
@name ||= self.class.name.demodulize.underscore
|
|
321
259
|
end
|
|
322
260
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
RubyProf.cpu_frequency = 2.33e9 unless RubyProf.cpu_frequency > 0
|
|
329
|
-
super
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
def measure
|
|
333
|
-
RubyProf.measure_cpu_time
|
|
261
|
+
def benchmark
|
|
262
|
+
with_gc_stats do
|
|
263
|
+
before = measure
|
|
264
|
+
yield
|
|
265
|
+
@total += (measure - before)
|
|
334
266
|
end
|
|
335
267
|
end
|
|
336
268
|
|
|
337
|
-
|
|
338
|
-
|
|
269
|
+
# overridden by each implementation
|
|
270
|
+
def profile; end
|
|
339
271
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
# Ruby 1.8 + ruby-prof wrapper
|
|
347
|
-
elsif RubyProf.respond_to?(:measure_memory)
|
|
348
|
-
def measure
|
|
349
|
-
RubyProf.measure_memory / 1024.0
|
|
350
|
-
end
|
|
351
|
-
end
|
|
272
|
+
protected
|
|
273
|
+
# overridden by each implementation
|
|
274
|
+
def with_gc_stats; end
|
|
275
|
+
end
|
|
352
276
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
277
|
+
class Time < Base
|
|
278
|
+
def measure
|
|
279
|
+
::Time.now.to_f
|
|
356
280
|
end
|
|
357
281
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
def measure
|
|
364
|
-
GC.malloc_allocations
|
|
365
|
-
end
|
|
366
|
-
|
|
367
|
-
# Ruby 1.8 + ruby-prof wrapper
|
|
368
|
-
elsif RubyProf.respond_to?(:measure_allocations)
|
|
369
|
-
def measure
|
|
370
|
-
RubyProf.measure_allocations
|
|
371
|
-
end
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
def format(measurement)
|
|
375
|
-
measurement.to_i.to_s
|
|
282
|
+
def format(measurement)
|
|
283
|
+
if measurement < 1
|
|
284
|
+
'%d ms' % (measurement * 1000)
|
|
285
|
+
else
|
|
286
|
+
'%.2f sec' % measurement
|
|
376
287
|
end
|
|
377
288
|
end
|
|
289
|
+
end
|
|
378
290
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
# Ruby 1.9
|
|
383
|
-
if GC.respond_to?(:count)
|
|
384
|
-
def measure
|
|
385
|
-
GC.count
|
|
386
|
-
end
|
|
387
|
-
|
|
388
|
-
# Ruby 1.8 + ruby-prof wrapper
|
|
389
|
-
elsif RubyProf.respond_to?(:measure_gc_runs)
|
|
390
|
-
def measure
|
|
391
|
-
RubyProf.measure_gc_runs
|
|
392
|
-
end
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
def format(measurement)
|
|
396
|
-
measurement.to_i.to_s
|
|
397
|
-
end
|
|
291
|
+
class Amount < Base
|
|
292
|
+
def format(measurement)
|
|
293
|
+
number_with_delimiter(measurement.floor)
|
|
398
294
|
end
|
|
295
|
+
end
|
|
399
296
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
# Ruby 1.9 with GC::Profiler
|
|
404
|
-
if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time)
|
|
405
|
-
def measure
|
|
406
|
-
GC::Profiler.total_time
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
# Ruby 1.8 + ruby-prof wrapper
|
|
410
|
-
elsif RubyProf.respond_to?(:measure_gc_time)
|
|
411
|
-
def measure
|
|
412
|
-
RubyProf.measure_gc_time / 1000
|
|
413
|
-
end
|
|
414
|
-
end
|
|
415
|
-
|
|
416
|
-
def format(measurement)
|
|
417
|
-
'%.2f ms' % measurement
|
|
418
|
-
end
|
|
297
|
+
class DigitalInformationUnit < Base
|
|
298
|
+
def format(measurement)
|
|
299
|
+
number_to_human_size(measurement, :precision => 2)
|
|
419
300
|
end
|
|
420
301
|
end
|
|
302
|
+
|
|
303
|
+
# each implementation provides its own metrics like ProcessTime, Memory or GcRuns
|
|
421
304
|
end
|
|
422
305
|
end
|
|
423
306
|
end
|
|
424
|
-
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
RUBY_ENGINE = 'ruby' unless defined?(RUBY_ENGINE) # mri 1.8
|
|
310
|
+
case RUBY_ENGINE
|
|
311
|
+
when 'ruby' then require 'active_support/testing/performance/ruby'
|
|
312
|
+
when 'rbx' then require 'active_support/testing/performance/rubinius'
|
|
313
|
+
when 'jruby' then require 'active_support/testing/performance/jruby'
|
|
314
|
+
else
|
|
315
|
+
$stderr.puts 'Your ruby interpreter is not supported for benchmarking.'
|
|
316
|
+
exit
|
|
425
317
|
end
|