activesupport 3.1.0.beta1 → 3.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (46) hide show
  1. data/CHANGELOG +33 -1
  2. data/README.rdoc +1 -1
  3. data/lib/active_support.rb +1 -1
  4. data/lib/active_support/buffered_logger.rb +9 -4
  5. data/lib/active_support/configurable.rb +9 -6
  6. data/lib/active_support/core_ext/array/conversions.rb +2 -2
  7. data/lib/active_support/core_ext/array/random_access.rb +1 -1
  8. data/lib/active_support/core_ext/array/uniq_by.rb +2 -3
  9. data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -2
  10. data/lib/active_support/core_ext/date/calculations.rb +3 -3
  11. data/lib/active_support/core_ext/date/conversions.rb +3 -2
  12. data/lib/active_support/core_ext/date_time/conversions.rb +8 -8
  13. data/lib/active_support/core_ext/hash/conversions.rb +2 -1
  14. data/lib/active_support/core_ext/hash/indifferent_access.rb +12 -0
  15. data/lib/active_support/core_ext/hash/slice.rb +1 -1
  16. data/lib/active_support/core_ext/integer/inflections.rb +7 -4
  17. data/lib/active_support/core_ext/kernel/reporting.rb +13 -1
  18. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +1 -0
  19. data/lib/active_support/core_ext/module/deprecation.rb +0 -2
  20. data/lib/active_support/core_ext/numeric/time.rb +2 -0
  21. data/lib/active_support/core_ext/object/blank.rb +3 -3
  22. data/lib/active_support/core_ext/object/duplicable.rb +2 -0
  23. data/lib/active_support/core_ext/object/try.rb +2 -0
  24. data/lib/active_support/core_ext/object/with_options.rb +8 -5
  25. data/lib/active_support/core_ext/string/behavior.rb +1 -2
  26. data/lib/active_support/core_ext/string/exclude.rb +1 -1
  27. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  28. data/lib/active_support/core_ext/time/calculations.rb +4 -3
  29. data/lib/active_support/core_ext/time/marshal.rb +1 -0
  30. data/lib/active_support/descendants_tracker.rb +9 -7
  31. data/lib/active_support/duration.rb +1 -0
  32. data/lib/active_support/hash_with_indifferent_access.rb +12 -4
  33. data/lib/active_support/inflector/methods.rb +5 -3
  34. data/lib/active_support/json/encoding.rb +4 -1
  35. data/lib/active_support/log_subscriber/test_helper.rb +1 -0
  36. data/lib/active_support/ordered_hash.rb +4 -0
  37. data/lib/active_support/secure_random.rb +3 -202
  38. data/lib/active_support/testing/performance.rb +227 -335
  39. data/lib/active_support/testing/performance/jruby.rb +115 -0
  40. data/lib/active_support/testing/performance/rubinius.rb +113 -0
  41. data/lib/active_support/testing/performance/ruby.rb +152 -0
  42. data/lib/active_support/testing/performance/ruby/mri.rb +59 -0
  43. data/lib/active_support/testing/performance/ruby/yarv.rb +57 -0
  44. data/lib/active_support/version.rb +1 -1
  45. data/lib/active_support/xml_mini.rb +4 -1
  46. metadata +8 -3
@@ -0,0 +1,115 @@
1
+ require 'jruby/profiler'
2
+ require 'java'
3
+ import java.lang.management.ManagementFactory
4
+
5
+ module ActiveSupport
6
+ module Testing
7
+ module Performance
8
+ DEFAULTS.merge!(
9
+ if ARGV.include?('--benchmark')
10
+ {:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time]}
11
+ else
12
+ { :metrics => [:wall_time],
13
+ :formats => [:flat, :graph] }
14
+ end).freeze
15
+
16
+ protected
17
+ def run_gc
18
+ ManagementFactory.memory_mx_bean.gc
19
+ end
20
+
21
+ class Profiler < Performer
22
+ def initialize(*args)
23
+ super
24
+ @supported = @metric.is_a?(Metrics::WallTime)
25
+ end
26
+
27
+ def run
28
+ return unless @supported
29
+
30
+ @total = time_with_block do
31
+ @data = JRuby::Profiler.profile do
32
+ full_profile_options[:runs].to_i.times { run_test(@metric, :profile) }
33
+ end
34
+ end
35
+ end
36
+
37
+ def record
38
+ return unless @supported
39
+
40
+ klasses = full_profile_options[:formats].map { |f| JRuby::Profiler.const_get("#{f.to_s.camelize}ProfilePrinter") }.compact
41
+
42
+ klasses.each do |klass|
43
+ fname = output_filename(klass)
44
+ FileUtils.mkdir_p(File.dirname(fname))
45
+ file = File.open(fname, 'wb') do |file|
46
+ klass.new(@data).printProfile(file)
47
+ end
48
+ end
49
+ end
50
+
51
+ protected
52
+ def output_filename(printer_class)
53
+ suffix =
54
+ case printer_class.name.demodulize
55
+ when 'FlatProfilePrinter'; 'flat.txt'
56
+ when 'GraphProfilePrinter'; 'graph.txt'
57
+ else printer_class.name.sub(/ProfilePrinter$/, '').underscore
58
+ end
59
+
60
+ "#{super()}_#{suffix}"
61
+ end
62
+ end
63
+
64
+ module Metrics
65
+ class Base
66
+ def profile
67
+ yield
68
+ end
69
+
70
+ protected
71
+ def with_gc_stats
72
+ ManagementFactory.memory_mx_bean.gc
73
+ yield
74
+ end
75
+ end
76
+
77
+ class WallTime < Time
78
+ def measure
79
+ super
80
+ end
81
+ end
82
+
83
+ class CpuTime < Time
84
+ def measure
85
+ ManagementFactory.thread_mx_bean.get_current_thread_cpu_time / 1000 / 1000 / 1000.0 # seconds
86
+ end
87
+ end
88
+
89
+ class UserTime < Time
90
+ def measure
91
+ ManagementFactory.thread_mx_bean.get_current_thread_user_time / 1000 / 1000 / 1000.0 # seconds
92
+ end
93
+ end
94
+
95
+ class Memory < DigitalInformationUnit
96
+ def measure
97
+ ManagementFactory.memory_mx_bean.non_heap_memory_usage.used + ManagementFactory.memory_mx_bean.heap_memory_usage.used
98
+ end
99
+ end
100
+
101
+ class GcRuns < Amount
102
+ def measure
103
+ ManagementFactory.garbage_collector_mx_beans.inject(0) { |total_runs, current_gc| total_runs += current_gc.collection_count }
104
+ end
105
+ end
106
+
107
+ class GcTime < Time
108
+ def measure
109
+ ManagementFactory.garbage_collector_mx_beans.inject(0) { |total_time, current_gc| total_time += current_gc.collection_time } / 1000.0 # seconds
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,113 @@
1
+ require 'rubinius/agent'
2
+
3
+ module ActiveSupport
4
+ module Testing
5
+ module Performance
6
+ DEFAULTS.merge!(
7
+ if ARGV.include?('--benchmark')
8
+ {:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]}
9
+ else
10
+ { :metrics => [:wall_time],
11
+ :formats => [:flat, :graph] }
12
+ end).freeze
13
+
14
+ protected
15
+ def run_gc
16
+ GC.run(true)
17
+ end
18
+
19
+ class Performer; end
20
+
21
+ class Profiler < Performer
22
+ def initialize(*args)
23
+ super
24
+ @supported = @metric.is_a?(Metrics::WallTime)
25
+ end
26
+
27
+ def run
28
+ return unless @supported
29
+
30
+ @profiler = Rubinius::Profiler::Instrumenter.new
31
+
32
+ @total = time_with_block do
33
+ @profiler.profile(false) do
34
+ full_profile_options[:runs].to_i.times { run_test(@metric, :profile) }
35
+ end
36
+ end
37
+ end
38
+
39
+ def record
40
+ return unless @supported
41
+
42
+ if(full_profile_options[:formats].include?(:flat))
43
+ create_path_and_open_file(:flat) do |file|
44
+ @profiler.show(file)
45
+ end
46
+ end
47
+
48
+ if(full_profile_options[:formats].include?(:graph))
49
+ create_path_and_open_file(:graph) do |file|
50
+ @profiler.show(file)
51
+ end
52
+ end
53
+ end
54
+
55
+ protected
56
+ def create_path_and_open_file(printer_name)
57
+ fname = "#{output_filename}_#{printer_name}.txt"
58
+ FileUtils.mkdir_p(File.dirname(fname))
59
+ File.open(fname, 'wb') do |file|
60
+ yield(file)
61
+ end
62
+ end
63
+ end
64
+
65
+ module Metrics
66
+ class Base
67
+ attr_reader :loopback
68
+
69
+ def profile
70
+ yield
71
+ end
72
+
73
+ protected
74
+ def with_gc_stats
75
+ @loopback = Rubinius::Agent.loopback
76
+ GC.run(true)
77
+ yield
78
+ end
79
+ end
80
+
81
+ class WallTime < Time
82
+ def measure
83
+ super
84
+ end
85
+ end
86
+
87
+ class Memory < DigitalInformationUnit
88
+ def measure
89
+ loopback.get("system.memory.counter.bytes").last
90
+ end
91
+ end
92
+
93
+ class Objects < Amount
94
+ def measure
95
+ loopback.get("system.memory.counter.objects").last
96
+ end
97
+ end
98
+
99
+ class GcRuns < Amount
100
+ def measure
101
+ loopback.get("system.gc.full.count").last + loopback.get("system.gc.young.count").last
102
+ end
103
+ end
104
+
105
+ class GcTime < Time
106
+ def measure
107
+ (loopback.get("system.gc.full.wallclock").last + loopback.get("system.gc.young.wallclock").last) / 1000.0
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,152 @@
1
+ begin
2
+ require 'ruby-prof'
3
+ rescue LoadError
4
+ $stderr.puts 'Specify ruby-prof as application\'s dependency in Gemfile to run benchmarks.'
5
+ exit
6
+ end
7
+
8
+ module ActiveSupport
9
+ module Testing
10
+ module Performance
11
+ DEFAULTS.merge!(
12
+ if ARGV.include?('--benchmark')
13
+ { :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time] }
14
+ else
15
+ { :min_percent => 0.01,
16
+ :metrics => [:process_time, :memory, :objects],
17
+ :formats => [:flat, :graph_html, :call_tree, :call_stack] }
18
+ end).freeze
19
+
20
+ protected
21
+ def run_gc
22
+ GC.start
23
+ end
24
+
25
+ class Profiler < Performer
26
+ def initialize(*args)
27
+ super
28
+ @supported = @metric.measure_mode rescue false
29
+ end
30
+
31
+ def run
32
+ return unless @supported
33
+
34
+ RubyProf.measure_mode = @metric.measure_mode
35
+ RubyProf.start
36
+ RubyProf.pause
37
+ full_profile_options[:runs].to_i.times { run_test(@metric, :profile) }
38
+ @data = RubyProf.stop
39
+ @total = @data.threads.values.sum(0) { |method_infos| method_infos.max.total_time }
40
+ end
41
+
42
+ def record
43
+ return unless @supported
44
+
45
+ klasses = full_profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact
46
+
47
+ klasses.each do |klass|
48
+ fname = output_filename(klass)
49
+ FileUtils.mkdir_p(File.dirname(fname))
50
+ File.open(fname, 'wb') do |file|
51
+ klass.new(@data).print(file, full_profile_options.slice(:min_percent))
52
+ end
53
+ end
54
+ end
55
+
56
+ protected
57
+ def output_filename(printer_class)
58
+ suffix =
59
+ case printer_class.name.demodulize
60
+ when 'FlatPrinter'; 'flat.txt'
61
+ when 'FlatPrinterWithLineNumbers'; 'flat_line_numbers.txt'
62
+ when 'GraphPrinter'; 'graph.txt'
63
+ when 'GraphHtmlPrinter'; 'graph.html'
64
+ when 'GraphYamlPrinter'; 'graph.yml'
65
+ when 'CallTreePrinter'; 'tree.txt'
66
+ when 'CallStackPrinter'; 'stack.html'
67
+ when 'DotPrinter'; 'graph.dot'
68
+ else printer_class.name.sub(/Printer$/, '').underscore
69
+ end
70
+
71
+ "#{super()}_#{suffix}"
72
+ end
73
+ end
74
+
75
+ module Metrics
76
+ class Base
77
+ def measure_mode
78
+ self.class::Mode
79
+ end
80
+
81
+ def profile
82
+ RubyProf.resume
83
+ yield
84
+ ensure
85
+ RubyProf.pause
86
+ end
87
+
88
+ protected
89
+ # overridden by each implementation
90
+ def with_gc_stats
91
+ yield
92
+ end
93
+ end
94
+
95
+ class ProcessTime < Time
96
+ Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME)
97
+
98
+ def measure
99
+ RubyProf.measure_process_time
100
+ end
101
+ end
102
+
103
+ class WallTime < Time
104
+ Mode = RubyProf::WALL_TIME if RubyProf.const_defined?(:WALL_TIME)
105
+
106
+ def measure
107
+ RubyProf.measure_wall_time
108
+ end
109
+ end
110
+
111
+ class CpuTime < Time
112
+ Mode = RubyProf::CPU_TIME if RubyProf.const_defined?(:CPU_TIME)
113
+
114
+ def initialize(*args)
115
+ # FIXME: yeah my CPU is 2.33 GHz
116
+ RubyProf.cpu_frequency = 2.33e9 unless RubyProf.cpu_frequency > 0
117
+ super
118
+ end
119
+
120
+ def measure
121
+ RubyProf.measure_cpu_time
122
+ end
123
+ end
124
+
125
+ class Memory < DigitalInformationUnit
126
+ Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY)
127
+ end
128
+
129
+ class Objects < Amount
130
+ Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS)
131
+ end
132
+
133
+ class GcRuns < Amount
134
+ Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS)
135
+ end
136
+
137
+ class GcTime < Time
138
+ Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME)
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ if RUBY_VERSION.between?('1.9.2', '2.0')
146
+ require 'active_support/testing/performance/ruby/yarv'
147
+ elsif RUBY_VERSION.between?('1.8.6', '1.9')
148
+ require 'active_support/testing/performance/ruby/mri'
149
+ else
150
+ $stderr.puts 'Update your ruby interpreter to be able to run benchmarks.'
151
+ exit
152
+ end
@@ -0,0 +1,59 @@
1
+ module ActiveSupport
2
+ module Testing
3
+ module Performance
4
+ module Metrics
5
+ class Base
6
+ protected
7
+ # Ruby 1.8 + ruby-prof wrapper (enable/disable stats for Benchmarker)
8
+ if GC.respond_to?(:enable_stats)
9
+ def with_gc_stats
10
+ GC.enable_stats
11
+ GC.start
12
+ yield
13
+ ensure
14
+ GC.disable_stats
15
+ end
16
+ end
17
+ end
18
+
19
+ class Memory < DigitalInformationUnit
20
+ # Ruby 1.8 + ruby-prof wrapper
21
+ if RubyProf.respond_to?(:measure_memory)
22
+ def measure
23
+ RubyProf.measure_memory
24
+ end
25
+ end
26
+ end
27
+
28
+ class Objects < Amount
29
+ # Ruby 1.8 + ruby-prof wrapper
30
+ if RubyProf.respond_to?(:measure_allocations)
31
+ def measure
32
+ RubyProf.measure_allocations
33
+ end
34
+ end
35
+ end
36
+
37
+ class GcRuns < Amount
38
+ # Ruby 1.8 + ruby-prof wrapper
39
+ if RubyProf.respond_to?(:measure_gc_runs)
40
+ def measure
41
+ RubyProf.measure_gc_runs
42
+ end
43
+ end
44
+ end
45
+
46
+ class GcTime < Time
47
+ # Ruby 1.8 + ruby-prof wrapper
48
+ if RubyProf.respond_to?(:measure_gc_time)
49
+ def measure
50
+ RubyProf.measure_gc_time / 1000.0 / 1000.0
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+
@@ -0,0 +1,57 @@
1
+ module ActiveSupport
2
+ module Testing
3
+ module Performance
4
+ module Metrics
5
+ class Base
6
+ protected
7
+ # Ruby 1.9 with GC::Profiler
8
+ if defined?(GC::Profiler)
9
+ def with_gc_stats
10
+ GC::Profiler.enable
11
+ GC.start
12
+ yield
13
+ ensure
14
+ GC::Profiler.disable
15
+ end
16
+ end
17
+ end
18
+
19
+ class Memory < DigitalInformationUnit
20
+ # Ruby 1.9 + GCdata patch
21
+ if GC.respond_to?(:malloc_allocated_size)
22
+ def measure
23
+ GC.malloc_allocated_size
24
+ end
25
+ end
26
+ end
27
+
28
+ class Objects < Amount
29
+ # Ruby 1.9 + GCdata patch
30
+ if GC.respond_to?(:malloc_allocations)
31
+ def measure
32
+ GC.malloc_allocations
33
+ end
34
+ end
35
+ end
36
+
37
+ class GcRuns < Amount
38
+ # Ruby 1.9
39
+ if GC.respond_to?(:count)
40
+ def measure
41
+ GC.count
42
+ end
43
+ end
44
+ end
45
+
46
+ class GcTime < Time
47
+ # Ruby 1.9 with GC::Profiler
48
+ if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time)
49
+ def measure
50
+ GC::Profiler.total_time
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end