aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonçalo Silva <goncalossilva@gmail.com>2011-03-25 01:49:21 +0000
committerGonçalo Silva <goncalossilva@gmail.com>2011-03-25 01:50:07 +0000
commitc50df6351cf0d8ff50e62995b1124fd8183eafc3 (patch)
tree275b0bd8afa88bc8a35e19e88c574cf5c751ebc6
parent6e99bb6acaf30f2b8cfacb82143dc1d1c761d47f (diff)
downloadrails-c50df6351cf0d8ff50e62995b1124fd8183eafc3.tar.gz
rails-c50df6351cf0d8ff50e62995b1124fd8183eafc3.tar.bz2
rails-c50df6351cf0d8ff50e62995b1124fd8183eafc3.zip
initial separation of RubyProf-specific code
-rw-r--r--activesupport/lib/active_support/testing/performance.rb223
-rw-r--r--activesupport/lib/active_support/testing/performance/mri.rb236
2 files changed, 241 insertions, 218 deletions
diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb
index fe68428a8a..18e9898fe5 100644
--- a/activesupport/lib/active_support/testing/performance.rb
+++ b/activesupport/lib/active_support/testing/performance.rb
@@ -10,11 +10,13 @@ if !defined?(RUBY_ENGINE) or RUBY_ENGINE == "ruby" # MRI 1.8 or 1.9
$stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks."
exit
end
+
+ require 'active_support/testing/performance/mri'
end
module ActiveSupport
module Testing
- module Performance
+ module Performance
DEFAULTS =
if benchmark = ARGV.include?('--benchmark') # HAX for rake test
{ :benchmark => true,
@@ -78,16 +80,6 @@ module ActiveSupport
end
protected
- def run_warmup
- GC.start
-
- time = Metrics::Time.new
- run_test(time, :benchmark)
- puts "%s (%s warmup)" % [full_test_name, time.format(time.total)]
-
- GC.start
- end
-
def run_profile(metric)
klass = profile_options[:benchmark] ? Benchmarker : Profiler
performer = klass.new(self, metric)
@@ -169,65 +161,7 @@ module ActiveSupport
"#{super}.csv"
end
end
-
- class Profiler < Performer
- def initialize(*args)
- super
- @supported = @metric.measure_mode rescue false
- end
-
- def run
- return unless @supported
-
- RubyProf.measure_mode = @metric.measure_mode
- RubyProf.start
- RubyProf.pause
- profile_options[:runs].to_i.times { run_test(@metric, :profile) }
- @data = RubyProf.stop
- @total = @data.threads.values.sum(0) { |method_infos| method_infos.max.total_time }
- end
-
- def report
- if @supported
- super
- else
- '%20s: unsupported' % @metric.name
- end
- end
-
- def record
- return unless @supported
-
- klasses = profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact
-
- klasses.each do |klass|
- fname = output_filename(klass)
- FileUtils.mkdir_p(File.dirname(fname))
- File.open(fname, 'wb') do |file|
- klass.new(@data).print(file, profile_options.slice(:min_percent))
- end
- end
- end
-
- protected
- def output_filename(printer_class)
- suffix =
- case printer_class.name.demodulize
- when 'FlatPrinter'; 'flat.txt'
- when 'FlatPrinterWithLineNumbers'; 'flat_line_numbers.txt'
- when 'GraphPrinter'; 'graph.txt'
- when 'GraphHtmlPrinter'; 'graph.html'
- when 'GraphYamlPrinter'; 'graph.yml'
- when 'CallTreePrinter'; 'tree.txt'
- when 'CallStackPrinter'; 'stack.html'
- when 'DotPrinter'; 'graph.dot'
- else printer_class.name.sub(/Printer$/, '').underscore
- end
-
- "#{super()}_#{suffix}"
- end
- end
-
+
module Metrics
def self.[](name)
const_get(name.to_s.camelize)
@@ -261,41 +195,8 @@ module ActiveSupport
@total += (measure - before)
end
end
-
- def profile
- RubyProf.resume
- yield
- ensure
- RubyProf.pause
- end
-
- protected
- # Ruby 1.9 with GC::Profiler
- if defined?(GC::Profiler)
- def with_gc_stats
- GC::Profiler.enable
- GC.start
- yield
- ensure
- GC::Profiler.disable
- end
-
- # Ruby 1.8 + ruby-prof wrapper (enable/disable stats for Benchmarker)
- elsif GC.respond_to?(:enable_stats)
- def with_gc_stats
- GC.enable_stats
- yield
- ensure
- GC.disable_stats
- end
-
- else
- def with_gc_stats
- yield
- end
- end
end
-
+
class Time < Base
def measure
::Time.now.to_f
@@ -309,120 +210,6 @@ module ActiveSupport
end
end
end
-
- class ProcessTime < Time
- Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME)
-
- def measure
- RubyProf.measure_process_time
- end
- end
-
- class WallTime < Time
- Mode = RubyProf::WALL_TIME if RubyProf.const_defined?(:WALL_TIME)
-
- def measure
- RubyProf.measure_wall_time
- end
- end
-
- class CpuTime < Time
- Mode = RubyProf::CPU_TIME if RubyProf.const_defined?(:CPU_TIME)
-
- def initialize(*args)
- # FIXME: yeah my CPU is 2.33 GHz
- RubyProf.cpu_frequency = 2.33e9 unless RubyProf.cpu_frequency > 0
- super
- end
-
- def measure
- RubyProf.measure_cpu_time
- end
- end
-
- class Memory < Base
- Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY)
-
- # Ruby 1.9 + GCdata patch
- if GC.respond_to?(:malloc_allocated_size)
- def measure
- GC.malloc_allocated_size / 1024.0
- end
-
- # Ruby 1.8 + ruby-prof wrapper
- elsif RubyProf.respond_to?(:measure_memory)
- def measure
- RubyProf.measure_memory / 1024.0
- end
- end
-
- def format(measurement)
- '%.2f KB' % measurement
- end
- end
-
- class Objects < Base
- Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS)
-
- # Ruby 1.9 + GCdata patch
- if GC.respond_to?(:malloc_allocations)
- def measure
- GC.malloc_allocations
- end
-
- # Ruby 1.8 + ruby-prof wrapper
- elsif RubyProf.respond_to?(:measure_allocations)
- def measure
- RubyProf.measure_allocations
- end
- end
-
- def format(measurement)
- measurement.to_i.to_s
- end
- end
-
- class GcRuns < Base
- Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS)
-
- # Ruby 1.9
- if GC.respond_to?(:count)
- def measure
- GC.count
- end
-
- # Ruby 1.8 + ruby-prof wrapper
- elsif RubyProf.respond_to?(:measure_gc_runs)
- def measure
- RubyProf.measure_gc_runs
- end
- end
-
- def format(measurement)
- measurement.to_i.to_s
- end
- end
-
- class GcTime < Base
- Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME)
-
- # Ruby 1.9 with GC::Profiler
- if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time)
- def measure
- GC::Profiler.total_time
- end
-
- # Ruby 1.8 + ruby-prof wrapper
- elsif RubyProf.respond_to?(:measure_gc_time)
- def measure
- RubyProf.measure_gc_time / 1000
- end
- end
-
- def format(measurement)
- '%.2f ms' % measurement
- end
- end
end
end
end
diff --git a/activesupport/lib/active_support/testing/performance/mri.rb b/activesupport/lib/active_support/testing/performance/mri.rb
new file mode 100644
index 0000000000..cfa48890dc
--- /dev/null
+++ b/activesupport/lib/active_support/testing/performance/mri.rb
@@ -0,0 +1,236 @@
+begin
+ require 'ruby-prof'
+rescue LoadError
+ $stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks."
+ exit
+end
+
+module ActiveSupport
+ module Testing
+ module Performance
+ protected
+ def run_warmup
+ GC.start
+
+ time = Metrics::Time.new
+ run_test(time, :benchmark)
+ puts "%s (%s warmup)" % [full_test_name, time.format(time.total)]
+
+ GC.start
+ end
+
+ class Performer; end
+
+ class Profiler < Performer
+ def initialize(*args)
+ super
+ @supported = @metric.measure_mode rescue false
+ end
+
+ def run
+ return unless @supported
+
+ RubyProf.measure_mode = @metric.measure_mode
+ RubyProf.start
+ RubyProf.pause
+ profile_options[:runs].to_i.times { run_test(@metric, :profile) }
+ @data = RubyProf.stop
+ @total = @data.threads.values.sum(0) { |method_infos| method_infos.max.total_time }
+ end
+
+ def report
+ if @supported
+ super
+ else
+ '%20s: unsupported' % @metric.name
+ end
+ end
+
+ def record
+ return unless @supported
+
+ klasses = profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact
+
+ klasses.each do |klass|
+ fname = output_filename(klass)
+ FileUtils.mkdir_p(File.dirname(fname))
+ File.open(fname, 'wb') do |file|
+ klass.new(@data).print(file, profile_options.slice(:min_percent))
+ end
+ end
+ end
+
+ protected
+ def output_filename(printer_class)
+ suffix =
+ case printer_class.name.demodulize
+ when 'FlatPrinter'; 'flat.txt'
+ when 'FlatPrinterWithLineNumbers'; 'flat_line_numbers.txt'
+ when 'GraphPrinter'; 'graph.txt'
+ when 'GraphHtmlPrinter'; 'graph.html'
+ when 'GraphYamlPrinter'; 'graph.yml'
+ when 'CallTreePrinter'; 'tree.txt'
+ when 'CallStackPrinter'; 'stack.html'
+ when 'DotPrinter'; 'graph.dot'
+ else printer_class.name.sub(/Printer$/, '').underscore
+ end
+
+ "#{super()}_#{suffix}"
+ end
+ end
+
+ module Metrics
+ class Base
+ def profile
+ RubyProf.resume
+ yield
+ ensure
+ RubyProf.pause
+ end
+
+ protected
+ # Ruby 1.9 with GC::Profiler
+ if defined?(GC::Profiler)
+ def with_gc_stats
+ GC::Profiler.enable
+ GC.start
+ yield
+ ensure
+ GC::Profiler.disable
+ end
+
+ # Ruby 1.8 + ruby-prof wrapper (enable/disable stats for Benchmarker)
+ elsif GC.respond_to?(:enable_stats)
+ def with_gc_stats
+ GC.enable_stats
+ yield
+ ensure
+ GC.disable_stats
+ end
+
+ else
+ def with_gc_stats
+ yield
+ end
+ end
+ end
+
+ class Time < Base; end
+
+ class ProcessTime < Time
+ Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME)
+
+ def measure
+ RubyProf.measure_process_time
+ end
+ end
+
+ class WallTime < Time
+ Mode = RubyProf::WALL_TIME if RubyProf.const_defined?(:WALL_TIME)
+
+ def measure
+ RubyProf.measure_wall_time
+ end
+ end
+
+ class CpuTime < Time
+ Mode = RubyProf::CPU_TIME if RubyProf.const_defined?(:CPU_TIME)
+
+ def initialize(*args)
+ # FIXME: yeah my CPU is 2.33 GHz
+ RubyProf.cpu_frequency = 2.33e9 unless RubyProf.cpu_frequency > 0
+ super
+ end
+
+ def measure
+ RubyProf.measure_cpu_time
+ end
+ end
+
+ class Memory < Base
+ Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY)
+
+ # Ruby 1.9 + GCdata patch
+ if GC.respond_to?(:malloc_allocated_size)
+ def measure
+ GC.malloc_allocated_size / 1024.0
+ end
+
+ # Ruby 1.8 + ruby-prof wrapper
+ elsif RubyProf.respond_to?(:measure_memory)
+ def measure
+ RubyProf.measure_memory / 1024.0
+ end
+ end
+
+ def format(measurement)
+ '%.2f KB' % measurement
+ end
+ end
+
+ class Objects < Base
+ Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS)
+
+ # Ruby 1.9 + GCdata patch
+ if GC.respond_to?(:malloc_allocations)
+ def measure
+ GC.malloc_allocations
+ end
+
+ # Ruby 1.8 + ruby-prof wrapper
+ elsif RubyProf.respond_to?(:measure_allocations)
+ def measure
+ RubyProf.measure_allocations
+ end
+ end
+
+ def format(measurement)
+ measurement.to_i.to_s
+ end
+ end
+
+ class GcRuns < Base
+ Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS)
+
+ # Ruby 1.9
+ if GC.respond_to?(:count)
+ def measure
+ GC.count
+ end
+
+ # Ruby 1.8 + ruby-prof wrapper
+ elsif RubyProf.respond_to?(:measure_gc_runs)
+ def measure
+ RubyProf.measure_gc_runs
+ end
+ end
+
+ def format(measurement)
+ measurement.to_i.to_s
+ end
+ end
+
+ class GcTime < Base
+ Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME)
+
+ # Ruby 1.9 with GC::Profiler
+ if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time)
+ def measure
+ GC::Profiler.total_time
+ end
+
+ # Ruby 1.8 + ruby-prof wrapper
+ elsif RubyProf.respond_to?(:measure_gc_time)
+ def measure
+ RubyProf.measure_gc_time / 1000
+ end
+ end
+
+ def format(measurement)
+ '%.2f ms' % measurement
+ end
+ end
+ end
+ end
+ end
+end