diff options
author | Gonçalo Silva <goncalossilva@gmail.com> | 2011-03-25 01:49:21 +0000 |
---|---|---|
committer | Gonçalo Silva <goncalossilva@gmail.com> | 2011-03-25 01:50:07 +0000 |
commit | c50df6351cf0d8ff50e62995b1124fd8183eafc3 (patch) | |
tree | 275b0bd8afa88bc8a35e19e88c574cf5c751ebc6 /activesupport/lib | |
parent | 6e99bb6acaf30f2b8cfacb82143dc1d1c761d47f (diff) | |
download | rails-c50df6351cf0d8ff50e62995b1124fd8183eafc3.tar.gz rails-c50df6351cf0d8ff50e62995b1124fd8183eafc3.tar.bz2 rails-c50df6351cf0d8ff50e62995b1124fd8183eafc3.zip |
initial separation of RubyProf-specific code
Diffstat (limited to 'activesupport/lib')
-rw-r--r-- | activesupport/lib/active_support/testing/performance.rb | 223 | ||||
-rw-r--r-- | activesupport/lib/active_support/testing/performance/mri.rb | 236 |
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 |