From 92c0f17d6d2a958d3a6285b0e5408e9e0e7122e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 18 Jun 2010 22:23:11 +0100 Subject: performance tests now working accurately on 1.9, using Ruby with the GCdata patch --- .../lib/active_support/testing/performance.rb | 54 ++++++++-------------- 1 file changed, 18 insertions(+), 36 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index cd628a956d..a124c6e0ca 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -260,16 +260,14 @@ begin end protected - # Ruby 1.9 + extented GC profiler patch - if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data) + # Ruby 1.9 with GC::Profiler + if defined?(GC::Profiler) def with_gc_stats - GC.start - GC.disable GC::Profiler.enable + GC.start yield ensure GC::Profiler.disable - GC.enable end # Ruby 1.8 + ruby-prof wrapper (enable/disable stats for Benchmarker) @@ -294,7 +292,7 @@ begin end def format(measurement) - if measurement < 2 + if measurement < 1 '%d ms' % (measurement * 1000) else '%.2f sec' % measurement @@ -335,14 +333,10 @@ begin class Memory < Base Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY) - # Ruby 1.9 + extended GC profiler patch - if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data) + # Ruby 1.9 + GCdata patch + if GC.respond_to?(:malloc_allocated_size) def measure - GC.enable - GC.start - kb = GC::Profiler.data.last[:HEAP_USE_SIZE] / 1024.0 - GC.disable - kb + GC.malloc_allocated_size / 1024.0 end # Ruby 1.8 + ruby-prof wrapper @@ -360,14 +354,10 @@ begin class Objects < Base Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS) - # Ruby 1.9 + extented GC profiler patch - if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data) + # Ruby 1.9 + GCdata patch + if GC.respond_to?(:malloc_allocations) def measure - GC.enable - GC.start - count = GC::Profiler.data.last[:HEAP_TOTAL_OBJECTS] - GC.disable - count + GC.malloc_allocations end # Ruby 1.8 + ruby-prof wrapper @@ -385,14 +375,10 @@ begin class GcRuns < Base Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS) - # Ruby 1.9 + extented GC profiler patch - if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data) + # Ruby 1.9 + if GC.respond_to?(:count) def measure - GC.enable - GC.start - count = GC::Profiler.data.last[:GC_RUNS] - GC.disable - count + GC.count end # Ruby 1.8 + ruby-prof wrapper @@ -410,25 +396,21 @@ begin class GcTime < Base Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME) - # Ruby 1.9 + extented GC profiler patch - if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data) + # Ruby 1.9 with GC::Profiler + if GC.respond_to?(:total_time) def measure - GC.enable - GC.start - sec = GC::Profiler.data.inject(0) { |total, run| total += run[:GC_TIME] } - GC.disable - sec + GC::Profiler.total_time end # Ruby 1.8 + ruby-prof wrapper elsif RubyProf.respond_to?(:measure_gc_time) def measure - RubyProf.measure_gc_time + RubyProf.measure_gc_time / 1000 end end def format(measurement) - '%d ms' % (measurement / 1000) + '%.2f ms' % measurement end end end -- cgit v1.2.3 From aff821508a16245ebc03510ba29c70379718dfb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Tue, 10 Aug 2010 18:21:51 +0100 Subject: added support for more printers --- activesupport/lib/active_support/testing/performance.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index a124c6e0ca..f7ddf6421d 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -178,7 +178,7 @@ begin 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.sort.last.total_time } + @total = @data.threads.values.sum(0) { |method_infos| method_infos.max.total_time } end def report @@ -207,10 +207,14 @@ begin def output_filename(printer_class) suffix = case printer_class.name.demodulize - when 'FlatPrinter'; 'flat.txt' - when 'GraphPrinter'; 'graph.txt' - when 'GraphHtmlPrinter'; 'graph.html' - when 'CallTreePrinter'; 'tree.txt' + 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 -- cgit v1.2.3 From 23be2c613490a06170ae50a72889957b006d36a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Thu, 24 Mar 2011 23:38:17 +0000 Subject: check if RubyProf's WALL_TIME and PROCESS_TIME are available before using them (similarly to other constants) --- activesupport/lib/active_support/testing/performance.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 8c91a061fb..42b58c4f25 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -305,7 +305,7 @@ begin end class ProcessTime < Time - Mode = RubyProf::PROCESS_TIME + Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME) def measure RubyProf.measure_process_time @@ -313,7 +313,7 @@ begin end class WallTime < Time - Mode = RubyProf::WALL_TIME + Mode = RubyProf::WALL_TIME if RubyProf.const_defined?(:WALL_TIME) def measure RubyProf.measure_wall_time -- cgit v1.2.3 From a6e22229b9501f846185306c49009404b4f8466e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Thu, 24 Mar 2011 23:57:57 +0000 Subject: move "check for ruby-prof" from AD/testing/performance_test to AS/testing/performance, where it is actually required --- .../lib/active_support/testing/performance.rb | 618 +++++++++++---------- 1 file changed, 310 insertions(+), 308 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 42b58c4f25..9e46e5963e 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -1,425 +1,427 @@ +require 'fileutils' +require 'rails/version' +require 'active_support/core_ext/class/delegating_attributes' +require 'active_support/core_ext/string/inflections' + begin require 'ruby-prof' +rescue LoadError + $stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks." + exit +end - require 'fileutils' - require 'rails/version' - require 'active_support/core_ext/class/delegating_attributes' - require 'active_support/core_ext/string/inflections' - - module ActiveSupport - module Testing - module Performance - DEFAULTS = - if benchmark = ARGV.include?('--benchmark') # HAX for rake test - { :benchmark => true, - :runs => 4, - :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time], - :output => 'tmp/performance' } - else - { :benchmark => false, - :runs => 1, - :min_percent => 0.01, - :metrics => [:process_time, :memory, :objects], - :formats => [:flat, :graph_html, :call_tree], - :output => 'tmp/performance' } - end.freeze - - def self.included(base) - base.superclass_delegating_accessor :profile_options - base.profile_options = DEFAULTS - end +module ActiveSupport + module Testing + module Performance + DEFAULTS = + if benchmark = ARGV.include?('--benchmark') # HAX for rake test + { :benchmark => true, + :runs => 4, + :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time], + :output => 'tmp/performance' } + else + { :benchmark => false, + :runs => 1, + :min_percent => 0.01, + :metrics => [:process_time, :memory, :objects], + :formats => [:flat, :graph_html, :call_tree], + :output => 'tmp/performance' } + end.freeze + + def self.included(base) + base.superclass_delegating_accessor :profile_options + base.profile_options = DEFAULTS + end - def full_test_name - "#{self.class.name}##{method_name}" - end + def full_test_name + "#{self.class.name}##{method_name}" + end - def run(result) - return if method_name =~ /^default_test$/ + def run(result) + return if method_name =~ /^default_test$/ - yield(self.class::STARTED, name) - @_result = result + yield(self.class::STARTED, name) + @_result = result - run_warmup - if profile_options && metrics = profile_options[:metrics] - metrics.each do |metric_name| - if klass = Metrics[metric_name.to_sym] - run_profile(klass.new) - result.add_run - end + run_warmup + if profile_options && metrics = profile_options[:metrics] + metrics.each do |metric_name| + if klass = Metrics[metric_name.to_sym] + run_profile(klass.new) + result.add_run end end - - yield(self.class::FINISHED, name) end - def run_test(metric, mode) - run_callbacks :setup - setup - metric.send(mode) { __send__ @method_name } + yield(self.class::FINISHED, name) + end + + def run_test(metric, mode) + run_callbacks :setup + setup + metric.send(mode) { __send__ @method_name } + rescue ::Test::Unit::AssertionFailedError => e + add_failure(e.message, e.backtrace) + rescue StandardError, ScriptError => e + add_error(e) + ensure + begin + teardown + run_callbacks :teardown, :enumerator => :reverse_each rescue ::Test::Unit::AssertionFailedError => e add_failure(e.message, e.backtrace) rescue StandardError, ScriptError => e add_error(e) - ensure - begin - teardown - run_callbacks :teardown, :enumerator => :reverse_each - rescue ::Test::Unit::AssertionFailedError => e - add_failure(e.message, e.backtrace) - rescue StandardError, ScriptError => e - add_error(e) - end end + end - protected - def run_warmup - GC.start + 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)] + time = Metrics::Time.new + run_test(time, :benchmark) + puts "%s (%s warmup)" % [full_test_name, time.format(time.total)] - GC.start - end + GC.start + end - def run_profile(metric) - klass = profile_options[:benchmark] ? Benchmarker : Profiler - performer = klass.new(self, metric) + def run_profile(metric) + klass = profile_options[:benchmark] ? Benchmarker : Profiler + performer = klass.new(self, metric) - performer.run - puts performer.report - performer.record - end + performer.run + puts performer.report + performer.record + end - class Performer - delegate :run_test, :profile_options, :full_test_name, :to => :@harness + class Performer + delegate :run_test, :profile_options, :full_test_name, :to => :@harness - def initialize(harness, metric) - @harness, @metric = harness, metric - end + def initialize(harness, metric) + @harness, @metric = harness, metric + end - def report - rate = @total / profile_options[:runs] - '%20s: %s' % [@metric.name, @metric.format(rate)] + def report + rate = @total / profile_options[:runs] + '%20s: %s' % [@metric.name, @metric.format(rate)] + end + + protected + def output_filename + "#{profile_options[:output]}/#{full_test_name}_#{@metric.name}" end + end - protected - def output_filename - "#{profile_options[:output]}/#{full_test_name}_#{@metric.name}" - end + class Benchmarker < Performer + def run + profile_options[:runs].to_i.times { run_test(@metric, :benchmark) } + @total = @metric.total end - class Benchmarker < Performer - def run - profile_options[:runs].to_i.times { run_test(@metric, :benchmark) } - @total = @metric.total + def record + avg = @metric.total / profile_options[:runs].to_i + now = Time.now.utc.xmlschema + with_output_file do |file| + file.puts "#{avg},#{now},#{environment}" end + end + + def environment + unless defined? @env + app = "#{$1}.#{$2}" if File.directory?('.git') && `git branch -v` =~ /^\* (\S+)\s+(\S+)/ - def record - avg = @metric.total / profile_options[:runs].to_i - now = Time.now.utc.xmlschema - with_output_file do |file| - file.puts "#{avg},#{now},#{environment}" + rails = Rails::VERSION::STRING + if File.directory?('vendor/rails/.git') + Dir.chdir('vendor/rails') do + rails += ".#{$1}.#{$2}" if `git branch -v` =~ /^\* (\S+)\s+(\S+)/ + end end + + ruby = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby' + ruby += "-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}" + + @env = [app, rails, ruby, RUBY_PLATFORM] * ',' end - def environment - unless defined? @env - app = "#{$1}.#{$2}" if File.directory?('.git') && `git branch -v` =~ /^\* (\S+)\s+(\S+)/ + @env + end - rails = Rails::VERSION::STRING - if File.directory?('vendor/rails/.git') - Dir.chdir('vendor/rails') do - rails += ".#{$1}.#{$2}" if `git branch -v` =~ /^\* (\S+)\s+(\S+)/ - end - end + protected + HEADER = 'measurement,created_at,app,rails,ruby,platform' - ruby = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby' - ruby += "-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}" + def with_output_file + fname = output_filename - @env = [app, rails, ruby, RUBY_PLATFORM] * ',' + if new = !File.exist?(fname) + FileUtils.mkdir_p(File.dirname(fname)) end - @env + File.open(fname, 'ab') do |file| + file.puts(HEADER) if new + yield file + end end - protected - HEADER = 'measurement,created_at,app,rails,ruby,platform' - - def with_output_file - fname = output_filename + def output_filename + "#{super}.csv" + end + end - if new = !File.exist?(fname) - FileUtils.mkdir_p(File.dirname(fname)) - end + class Profiler < Performer + def initialize(*args) + super + @supported = @metric.measure_mode rescue false + end - File.open(fname, 'ab') do |file| - file.puts(HEADER) if new - yield file - end - end + def run + return unless @supported - def output_filename - "#{super}.csv" - end + 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 - class Profiler < Performer - def initialize(*args) + def report + if @supported super - @supported = @metric.measure_mode rescue false + else + '%20s: unsupported' % @metric.name end + end - def run - return unless @supported + def record + 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 + klasses = profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact - def report - if @supported - super - else - '%20s: unsupported' % @metric.name + 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 - 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)) + 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 - end + + "#{super()}_#{suffix}" 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 + module Metrics + def self.[](name) + const_get(name.to_s.camelize) + rescue NameError + nil end - module Metrics - def self.[](name) - const_get(name.to_s.camelize) - rescue NameError - nil + class Base + attr_reader :total + + def initialize + @total = 0 end - class Base - attr_reader :total + def name + @name ||= self.class.name.demodulize.underscore + end - def initialize - @total = 0 - end + def measure_mode + self.class::Mode + end - def name - @name ||= self.class.name.demodulize.underscore - end + def measure + 0 + end - def measure_mode - self.class::Mode + def benchmark + with_gc_stats do + before = measure + yield + @total += (measure - before) end + end - def measure - 0 - end + def profile + RubyProf.resume + yield + ensure + RubyProf.pause + end - def benchmark - with_gc_stats do - before = measure + protected + # Ruby 1.9 with GC::Profiler + if defined?(GC::Profiler) + def with_gc_stats + GC::Profiler.enable + GC.start yield - @total += (measure - before) + ensure + GC::Profiler.disable 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 + # 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 - end - class Time < Base - def measure - ::Time.now.to_f - end - - def format(measurement) - if measurement < 1 - '%d ms' % (measurement * 1000) - else - '%.2f sec' % measurement + else + def with_gc_stats + yield end end - end + end - class ProcessTime < Time - Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME) + class Time < Base + def measure + ::Time.now.to_f + end - def measure - RubyProf.measure_process_time + def format(measurement) + if measurement < 1 + '%d ms' % (measurement * 1000) + else + '%.2f sec' % measurement end end + end - class WallTime < Time - Mode = RubyProf::WALL_TIME if RubyProf.const_defined?(:WALL_TIME) + class ProcessTime < Time + Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME) - def measure - RubyProf.measure_wall_time - end + def measure + RubyProf.measure_process_time end + end - class CpuTime < Time - Mode = RubyProf::CPU_TIME if RubyProf.const_defined?(:CPU_TIME) + class WallTime < Time + Mode = RubyProf::WALL_TIME if RubyProf.const_defined?(:WALL_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_wall_time + end + end - def measure - RubyProf.measure_cpu_time - 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 - class Memory < Base - Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY) + def measure + RubyProf.measure_cpu_time + end + end - # Ruby 1.9 + GCdata patch - if GC.respond_to?(:malloc_allocated_size) - def measure - GC.malloc_allocated_size / 1024.0 - end + class Memory < Base + Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY) - # Ruby 1.8 + ruby-prof wrapper - elsif RubyProf.respond_to?(:measure_memory) - def measure - RubyProf.measure_memory / 1024.0 - end + # Ruby 1.9 + GCdata patch + if GC.respond_to?(:malloc_allocated_size) + def measure + GC.malloc_allocated_size / 1024.0 end - def format(measurement) - '%.2f KB' % measurement + # Ruby 1.8 + ruby-prof wrapper + elsif RubyProf.respond_to?(:measure_memory) + def measure + RubyProf.measure_memory / 1024.0 end end - class Objects < Base - Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS) + def format(measurement) + '%.2f KB' % measurement + end + end - # Ruby 1.9 + GCdata patch - if GC.respond_to?(:malloc_allocations) - def measure - GC.malloc_allocations - end + class Objects < Base + Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS) - # Ruby 1.8 + ruby-prof wrapper - elsif RubyProf.respond_to?(:measure_allocations) - def measure - RubyProf.measure_allocations - end + # Ruby 1.9 + GCdata patch + if GC.respond_to?(:malloc_allocations) + def measure + GC.malloc_allocations end - def format(measurement) - measurement.to_i.to_s + # Ruby 1.8 + ruby-prof wrapper + elsif RubyProf.respond_to?(:measure_allocations) + def measure + RubyProf.measure_allocations end end - class GcRuns < Base - Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS) + def format(measurement) + measurement.to_i.to_s + end + end - # Ruby 1.9 - if GC.respond_to?(:count) - def measure - GC.count - end + class GcRuns < Base + Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS) - # Ruby 1.8 + ruby-prof wrapper - elsif RubyProf.respond_to?(:measure_gc_runs) - def measure - RubyProf.measure_gc_runs - end + # Ruby 1.9 + if GC.respond_to?(:count) + def measure + GC.count end - def format(measurement) - measurement.to_i.to_s + # Ruby 1.8 + ruby-prof wrapper + elsif RubyProf.respond_to?(:measure_gc_runs) + def measure + RubyProf.measure_gc_runs end end - class GcTime < Base - Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME) + def format(measurement) + measurement.to_i.to_s + end + end - # Ruby 1.9 with GC::Profiler - if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time) - def measure - GC::Profiler.total_time - end + class GcTime < Base + Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME) - # Ruby 1.8 + ruby-prof wrapper - elsif RubyProf.respond_to?(:measure_gc_time) - def measure - RubyProf.measure_gc_time / 1000 - end + # Ruby 1.9 with GC::Profiler + if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time) + def measure + GC::Profiler.total_time end - def format(measurement) - '%.2f ms' % measurement + # 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 -rescue LoadError end -- cgit v1.2.3 From 6e99bb6acaf30f2b8cfacb82143dc1d1c761d47f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 00:02:25 +0000 Subject: ruby-prof only makes sense in an MRI context --- activesupport/lib/active_support/testing/performance.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 9e46e5963e..fe68428a8a 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -3,11 +3,13 @@ require 'rails/version' require 'active_support/core_ext/class/delegating_attributes' require 'active_support/core_ext/string/inflections' -begin - require 'ruby-prof' -rescue LoadError - $stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks." - exit +if !defined?(RUBY_ENGINE) or RUBY_ENGINE == "ruby" # MRI 1.8 or 1.9 + begin + require 'ruby-prof' + rescue LoadError + $stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks." + exit + end end module ActiveSupport -- cgit v1.2.3 From c50df6351cf0d8ff50e62995b1124fd8183eafc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 01:49:21 +0000 Subject: initial separation of RubyProf-specific code --- .../lib/active_support/testing/performance.rb | 223 +------------------ .../lib/active_support/testing/performance/mri.rb | 236 +++++++++++++++++++++ 2 files changed, 241 insertions(+), 218 deletions(-) create mode 100644 activesupport/lib/active_support/testing/performance/mri.rb (limited to 'activesupport/lib') 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 -- cgit v1.2.3 From e57d264f3795537cc3a5be61d766f956f882a5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 02:28:38 +0000 Subject: extracted more generic methods, added a note for methods that need to be overridden by each implementation --- .../lib/active_support/testing/performance.rb | 99 +++++++++++++++++----- .../lib/active_support/testing/performance/mri.rb | 36 ++------ 2 files changed, 87 insertions(+), 48 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 18e9898fe5..db7611c4fa 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -3,17 +3,6 @@ require 'rails/version' require 'active_support/core_ext/class/delegating_attributes' require 'active_support/core_ext/string/inflections' -if !defined?(RUBY_ENGINE) or RUBY_ENGINE == "ruby" # MRI 1.8 or 1.9 - begin - require 'ruby-prof' - rescue LoadError - $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 @@ -80,6 +69,19 @@ module ActiveSupport end protected + # overridden by each implementation + def run_gc; end + + def run_warmup + run_gc + + time = Metrics::Time.new + run_test(time, :benchmark) + puts "%s (%s warmup)" % [full_test_name, time.format(time.total)] + + run_gc + end + def run_profile(metric) klass = profile_options[:benchmark] ? Benchmarker : Profiler performer = klass.new(self, metric) @@ -106,6 +108,13 @@ module ActiveSupport "#{profile_options[:output]}/#{full_test_name}_#{@metric.name}" end end + + # overridden by each implementation + class Profiler < Performer + def run; end + def report; end + def record; end + end class Benchmarker < Performer def run @@ -180,14 +189,6 @@ module ActiveSupport @name ||= self.class.name.demodulize.underscore end - def measure_mode - self.class::Mode - end - - def measure - 0 - end - def benchmark with_gc_stats do before = measure @@ -195,6 +196,13 @@ module ActiveSupport @total += (measure - before) end end + + # overridden by each implementation + def profile; end + + protected + # overridden by each implementation + def with_gc_stats; end end class Time < Base @@ -210,7 +218,60 @@ module ActiveSupport end end end + + class ProcessTime < Time + # overridden by each implementation + def measure; end + end + + class WallTime < Time + # overridden by each implementation + def measure; end + end + + class CpuTime < Time + # overridden by each implementation + def measure; end + end + + class Memory < Base + # overridden by each implementation + def measure; end + + def format(measurement) + '%.2f KB' % measurement + end + end + + class Objects < Base + # overridden by each implementation + def measure; end + + def format(measurement) + measurement.to_i.to_s + end + end + + class GcRuns < Base + # overridden by each implementation + def measure; end + + def format(measurement) + measurement.to_i.to_s + end + end + + class GcTime < Base + # overridden by each implementation + def measure; end + + def format(measurement) + '%.2f ms' % measurement + end + end end end end end + +require 'active_support/testing/performance/mri' diff --git a/activesupport/lib/active_support/testing/performance/mri.rb b/activesupport/lib/active_support/testing/performance/mri.rb index cfa48890dc..914e546090 100644 --- a/activesupport/lib/active_support/testing/performance/mri.rb +++ b/activesupport/lib/active_support/testing/performance/mri.rb @@ -8,17 +8,12 @@ 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)] - + def run_gc GC.start end - + class Performer; end class Profiler < Performer @@ -81,6 +76,10 @@ module ActiveSupport module Metrics class Base + def measure_mode + self.class::Mode + end + def profile RubyProf.resume yield @@ -107,11 +106,6 @@ module ActiveSupport ensure GC.disable_stats end - - else - def with_gc_stats - yield - end end end @@ -162,10 +156,6 @@ module ActiveSupport RubyProf.measure_memory / 1024.0 end end - - def format(measurement) - '%.2f KB' % measurement - end end class Objects < Base @@ -183,10 +173,6 @@ module ActiveSupport RubyProf.measure_allocations end end - - def format(measurement) - measurement.to_i.to_s - end end class GcRuns < Base @@ -204,10 +190,6 @@ module ActiveSupport RubyProf.measure_gc_runs end end - - def format(measurement) - measurement.to_i.to_s - end end class GcTime < Base @@ -225,10 +207,6 @@ module ActiveSupport RubyProf.measure_gc_time / 1000 end end - - def format(measurement) - '%.2f ms' % measurement - end end end end -- cgit v1.2.3 From 11516089212a67e154ec426787feb6f24ed7e129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 02:39:43 +0000 Subject: using number_helper to pretty print some results --- .../lib/active_support/testing/performance.rb | 29 ++++++++++------------ .../lib/active_support/testing/performance/mri.rb | 6 ++--- 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index db7611c4fa..0d7d405127 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -2,6 +2,7 @@ require 'fileutils' require 'rails/version' require 'active_support/core_ext/class/delegating_attributes' require 'active_support/core_ext/string/inflections' +require 'action_view/helpers/number_helper' module ActiveSupport module Testing @@ -179,6 +180,8 @@ module ActiveSupport end class Base + include ActionView::Helpers::NumberHelper + attr_reader :total def initialize @@ -219,6 +222,12 @@ module ActiveSupport end end + class Amount < Base + def format(measurement) + number_with_delimiter(measurement) + end + end + class ProcessTime < Time # overridden by each implementation def measure; end @@ -239,35 +248,23 @@ module ActiveSupport def measure; end def format(measurement) - '%.2f KB' % measurement + number_to_human_size(measurement, :precision => 2) end end - class Objects < Base + class Objects < Amount # overridden by each implementation def measure; end - - def format(measurement) - measurement.to_i.to_s - end end - class GcRuns < Base + class GcRuns < Amount # overridden by each implementation def measure; end - - def format(measurement) - measurement.to_i.to_s - end end - class GcTime < Base + class GcTime < Time # overridden by each implementation def measure; end - - def format(measurement) - '%.2f ms' % measurement - end end end end diff --git a/activesupport/lib/active_support/testing/performance/mri.rb b/activesupport/lib/active_support/testing/performance/mri.rb index 914e546090..859588c735 100644 --- a/activesupport/lib/active_support/testing/performance/mri.rb +++ b/activesupport/lib/active_support/testing/performance/mri.rb @@ -158,7 +158,7 @@ module ActiveSupport end end - class Objects < Base + class Objects < Amount Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS) # Ruby 1.9 + GCdata patch @@ -175,7 +175,7 @@ module ActiveSupport end end - class GcRuns < Base + class GcRuns < Amount Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS) # Ruby 1.9 @@ -192,7 +192,7 @@ module ActiveSupport end end - class GcTime < Base + class GcTime < Time Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME) # Ruby 1.9 with GC::Profiler -- cgit v1.2.3 From 18a81db6fca2994d2c3872b0cb6bfa78bb94b383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 02:46:57 +0000 Subject: check whether the user is using a supported ruby interpreter for benchmarking --- activesupport/lib/active_support/testing/performance.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 0d7d405127..351835553f 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -271,4 +271,10 @@ module ActiveSupport end end -require 'active_support/testing/performance/mri' +RUBY_ENGINE ||= "ruby" +case RUBY_ENGINE + when "ruby" then require 'active_support/testing/performance/mri' + else + $stderr.puts "Your ruby interpreter is not supported for benchmarking." + exit +end -- cgit v1.2.3 From 3ec79e4288df602301e26ae7b2f2b651ff745862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 02:59:11 +0000 Subject: renamed "mri" to "ruby", for consistency with RUBY_ENGINE --- .../lib/active_support/testing/performance.rb | 4 +- .../lib/active_support/testing/performance/mri.rb | 214 --------------------- .../lib/active_support/testing/performance/ruby.rb | 214 +++++++++++++++++++++ .../active_support/testing/performance/ruby/mri.rb | 0 .../testing/performance/ruby/yarv.rb | 0 5 files changed, 216 insertions(+), 216 deletions(-) delete mode 100644 activesupport/lib/active_support/testing/performance/mri.rb create mode 100644 activesupport/lib/active_support/testing/performance/ruby.rb create mode 100644 activesupport/lib/active_support/testing/performance/ruby/mri.rb create mode 100644 activesupport/lib/active_support/testing/performance/ruby/yarv.rb (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 351835553f..a7faf6267a 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -271,9 +271,9 @@ module ActiveSupport end end -RUBY_ENGINE ||= "ruby" +RUBY_ENGINE = "ruby" unless defined?(RUBY_ENGINE) case RUBY_ENGINE - when "ruby" then require 'active_support/testing/performance/mri' + when "ruby" then require 'active_support/testing/performance/ruby' else $stderr.puts "Your ruby interpreter is not supported for benchmarking." exit diff --git a/activesupport/lib/active_support/testing/performance/mri.rb b/activesupport/lib/active_support/testing/performance/mri.rb deleted file mode 100644 index 859588c735..0000000000 --- a/activesupport/lib/active_support/testing/performance/mri.rb +++ /dev/null @@ -1,214 +0,0 @@ -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_gc - 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 measure_mode - self.class::Mode - 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 - 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 - end - - class Objects < Amount - 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 - end - - class GcRuns < Amount - 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 - end - - class GcTime < Time - 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 - end - end - end - end -end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb new file mode 100644 index 0000000000..859588c735 --- /dev/null +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -0,0 +1,214 @@ +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_gc + 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 measure_mode + self.class::Mode + 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 + 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 + end + + class Objects < Amount + 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 + end + + class GcRuns < Amount + 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 + end + + class GcTime < Time + 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 + end + end + end + end +end diff --git a/activesupport/lib/active_support/testing/performance/ruby/mri.rb b/activesupport/lib/active_support/testing/performance/ruby/mri.rb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb new file mode 100644 index 0000000000..e69de29bb2 -- cgit v1.2.3 From 2fa426c9444dc6dd1b701592cf4d636739556b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 03:26:43 +0000 Subject: divide the ruby interpreter into mri and yarv for improved modularity --- .../lib/active_support/testing/performance/ruby.rb | 93 ++++++---------------- .../active_support/testing/performance/ruby/mri.rb | 60 ++++++++++++++ .../testing/performance/ruby/yarv.rb | 62 +++++++++++++++ 3 files changed, 145 insertions(+), 70 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index 859588c735..86287b2d45 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -8,7 +8,6 @@ end module ActiveSupport module Testing module Performance - protected def run_gc GC.start @@ -88,24 +87,9 @@ module ActiveSupport 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 + # overridden by each implementation + def with_gc_stats + yield end end @@ -143,72 +127,41 @@ module ActiveSupport 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 + + # overridden by each implementation + def measure; 0; end end class Objects < Amount 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 + + # overridden by each implementation + def measure; 0; end end class GcRuns < Amount 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 + + # overridden by each implementation + def measure; 0; end end class GcTime < Time 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 + # overridden by each implementation + def measure; 0; end end end end end end + +if RUBY_VERSION >= "1.9.2" + require 'active_support/testing/performance/ruby/yarv' +elsif RUBY_VERSION >= "1.8.6" + require 'active_support/testing/performance/ruby/mri' +else + $stderr.puts "Update your ruby interpreter to be able to run benchmarks." + exit +end diff --git a/activesupport/lib/active_support/testing/performance/ruby/mri.rb b/activesupport/lib/active_support/testing/performance/ruby/mri.rb index e69de29bb2..d12482b58f 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/mri.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/mri.rb @@ -0,0 +1,60 @@ +module ActiveSupport + module Testing + module Performance + module Metrics + class Base + protected + # Ruby 1.8 + ruby-prof wrapper (enable/disable stats for Benchmarker) + if GC.respond_to?(:enable_stats) + def with_gc_stats + GC.enable_stats + yield + ensure + GC.disable_stats + end + end + end + + class Memory < Base + # Ruby 1.8 + ruby-prof wrapper + if RubyProf.respond_to?(:measure_memory) + def measure + RubyProf.measure_memory / 1024.0 + end + end + end + + class Amount < Base; end + + class Objects < Amount + # Ruby 1.8 + ruby-prof wrapper + if RubyProf.respond_to?(:measure_allocations) + def measure + RubyProf.measure_allocations + end + end + end + + class GcRuns < Amount + # Ruby 1.8 + ruby-prof wrapper + if RubyProf.respond_to?(:measure_gc_runs) + def measure + RubyProf.measure_gc_runs + end + end + end + + class GcTime < Time + # Ruby 1.8 + ruby-prof wrapper + if RubyProf.respond_to?(:measure_gc_time) + def measure + RubyProf.measure_gc_time / 1000 + end + end + end + end + end + end +end + + diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb index e69de29bb2..1e6fa2f289 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb @@ -0,0 +1,62 @@ +module ActiveSupport + module Testing + module Performance + module Metrics + class Base + 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 + end + end + + class Memory < Base + # Ruby 1.9 + GCdata patch + if GC.respond_to?(:malloc_allocated_size) + def measure + GC.malloc_allocated_size / 1024.0 + end + end + end + + class Amount < Base; end + + class Objects < Amount + # Ruby 1.9 + GCdata patch + if GC.respond_to?(:malloc_allocations) + def measure + GC.malloc_allocations + end + end + end + + class GcRuns < Amount + # Ruby 1.9 + if GC.respond_to?(:count) + def measure + GC.count + end + end + end + + class GcTime < Time + # Ruby 1.9 with GC::Profiler + if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time) + def measure + GC::Profiler.total_time + end + end + end + end + end + end +end + + + -- cgit v1.2.3 From 995d543b6458f84b05bd75464c7c270f1dfb14d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 17:18:06 +0000 Subject: added basic structure for Rubinius --- .../lib/active_support/testing/performance.rb | 7 +-- .../active_support/testing/performance/rubinius.rb | 61 ++++++++++++++++++++++ .../lib/active_support/testing/performance/ruby.rb | 6 +-- 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 activesupport/lib/active_support/testing/performance/rubinius.rb (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index a7faf6267a..ae78fafe78 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -271,10 +271,11 @@ module ActiveSupport end end -RUBY_ENGINE = "ruby" unless defined?(RUBY_ENGINE) +RUBY_ENGINE = 'ruby' unless defined?(RUBY_ENGINE) # mri 1.8 case RUBY_ENGINE - when "ruby" then require 'active_support/testing/performance/ruby' + when 'ruby' then require 'active_support/testing/performance/ruby' + when 'rubinius' then require 'active_support/testing/performance/rubinius' else - $stderr.puts "Your ruby interpreter is not supported for benchmarking." + $stderr.puts 'Your ruby interpreter is not supported for benchmarking.' exit end diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb new file mode 100644 index 0000000000..c6725b988a --- /dev/null +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -0,0 +1,61 @@ +module ActiveSupport + module Testing + module Performance + protected + def run_gc + end + + module Metrics + class Base + def profile + yield + end + + protected + def with_gc_stats + yield + end + end + + class Time < Base; end + + class ProcessTime < Time + def measure; 0; end + end + + class WallTime < Time + def measure; 0; end + end + + class CpuTime < Time + def measure; 0; end + end + + class Memory < Base + def measure; 0; end + end + + class Objects < Amount + def measure; 0; end + end + + class GcRuns < Amount + def measure; 0; end + end + + class GcTime < Time + def measure; 0; end + end + end + end + end +end + +if RUBY_VERSION >= '1.9.2' + require 'active_support/testing/performance/ruby/yarv' +elsif RUBY_VERSION >= '1.8.6' + require 'active_support/testing/performance/ruby/mri' +else + $stderr.puts 'Update your ruby interpreter to be able to run benchmarks.' + exit +end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index 86287b2d45..f786b85925 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -157,11 +157,11 @@ module ActiveSupport end end -if RUBY_VERSION >= "1.9.2" +if RUBY_VERSION >= '1.9.2' require 'active_support/testing/performance/ruby/yarv' -elsif RUBY_VERSION >= "1.8.6" +elsif RUBY_VERSION >= '1.8.6' require 'active_support/testing/performance/ruby/mri' else - $stderr.puts "Update your ruby interpreter to be able to run benchmarks." + $stderr.puts 'Update your ruby interpreter to be able to run benchmarks.' exit end -- cgit v1.2.3 From b0beba2621a98af3bc00a8f932c330b82b676af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 17:21:32 +0000 Subject: rubinius returns "rbx" for RUBY_ENGINE, not "rubinius" --- activesupport/lib/active_support/testing/performance.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index ae78fafe78..9a759433b9 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -273,8 +273,8 @@ end RUBY_ENGINE = 'ruby' unless defined?(RUBY_ENGINE) # mri 1.8 case RUBY_ENGINE - when 'ruby' then require 'active_support/testing/performance/ruby' - when 'rubinius' then require 'active_support/testing/performance/rubinius' + when 'ruby' then require 'active_support/testing/performance/ruby' + when 'rbx' then require 'active_support/testing/performance/rubinius' else $stderr.puts 'Your ruby interpreter is not supported for benchmarking.' exit -- cgit v1.2.3 From 4fe86a3ea243a16e69bcb406e733fe500fe5ede8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 17:23:39 +0000 Subject: removed leftovers from the copy-paste from mri --- activesupport/lib/active_support/testing/performance/rubinius.rb | 9 --------- 1 file changed, 9 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index c6725b988a..f939719d30 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -50,12 +50,3 @@ module ActiveSupport end end end - -if RUBY_VERSION >= '1.9.2' - require 'active_support/testing/performance/ruby/yarv' -elsif RUBY_VERSION >= '1.8.6' - require 'active_support/testing/performance/ruby/mri' -else - $stderr.puts 'Update your ruby interpreter to be able to run benchmarks.' - exit -end -- cgit v1.2.3 From 9e9090f887b61f4dca1cf6ea74cb64e649e95719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 17:27:26 +0000 Subject: added missing require --- activesupport/lib/active_support/testing/performance/rubinius.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index f939719d30..d91337c469 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -1,3 +1,5 @@ +require 'rubinius/agent' + module ActiveSupport module Testing module Performance -- cgit v1.2.3 From cf29d90ef1894d8a3dc7291fd1a2068c5f04f738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 17:59:22 +0000 Subject: added time (wall, process, cpu) to rubinius' benchmarks --- .../lib/active_support/testing/performance/rubinius.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index d91337c469..55fdd9fc9c 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -5,16 +5,20 @@ module ActiveSupport module Performance protected def run_gc + GC.run(true) end - module Metrics - class Base + module Metrics + class Base + # TODO def profile yield end protected + # overridden by each implementation def with_gc_stats + GC.run(true) yield end end @@ -22,14 +26,18 @@ module ActiveSupport class Time < Base; end class ProcessTime < Time + # unsupported def measure; 0; end end class WallTime < Time - def measure; 0; end + def measure + super + end end class CpuTime < Time + # unsupported def measure; 0; end end -- cgit v1.2.3 From c58e063da0358bc30b3d2fb90c4f08fcd32831fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 18:00:29 +0000 Subject: added memory size and allocations to rubinius' benchmarks --- .../lib/active_support/testing/performance/rubinius.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index 55fdd9fc9c..2dd866aa4a 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -14,6 +14,10 @@ module ActiveSupport def profile yield end + + def loopback + @loopback ||= Rubinius::Agent.loopback + end protected # overridden by each implementation @@ -42,11 +46,15 @@ module ActiveSupport end class Memory < Base - def measure; 0; end + def measure + loopback.get("system.memory.counter.bytes").last + end end class Objects < Amount - def measure; 0; end + def measure + loopback.get("system.memory.counter.bytes").last + end end class GcRuns < Amount -- cgit v1.2.3 From 417b2baf0fafc48dbfdab8a81b15836599a0613e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 18:01:39 +0000 Subject: added gc info (runs, time) to rubinius' benchmarks --- activesupport/lib/active_support/testing/performance/rubinius.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index 2dd866aa4a..ef4d2bd493 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -58,11 +58,15 @@ module ActiveSupport end class GcRuns < Amount - def measure; 0; end + def measure + loopback.get("system.gc.full.count").last + loopback.get("system.gc.young.count").last + end end class GcTime < Time - def measure; 0; end + def measure + loopback.get("system.gc.full.wallclock").last + loopback.get("system.gc.young.wallclock").last + end end end end -- cgit v1.2.3 From 278344b3fab67fcc471f475992a86c3748a83e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Fri, 25 Mar 2011 19:03:59 +0000 Subject: fixed time and size units (should be seconds / bytes), fixed typo when counting memory allocations under rubinius --- .../lib/active_support/testing/performance/rubinius.rb | 13 ++++++------- .../lib/active_support/testing/performance/ruby.rb | 2 +- .../lib/active_support/testing/performance/ruby/mri.rb | 4 ++-- .../lib/active_support/testing/performance/ruby/yarv.rb | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index ef4d2bd493..b9c7061571 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -9,19 +9,18 @@ module ActiveSupport end module Metrics - class Base + class Base + attr_reader :loopback + # TODO def profile yield end - - def loopback - @loopback ||= Rubinius::Agent.loopback - end protected # overridden by each implementation def with_gc_stats + @loopback = Rubinius::Agent.loopback GC.run(true) yield end @@ -53,7 +52,7 @@ module ActiveSupport class Objects < Amount def measure - loopback.get("system.memory.counter.bytes").last + loopback.get("system.memory.counter.objects").last end end @@ -65,7 +64,7 @@ module ActiveSupport class GcTime < Time def measure - loopback.get("system.gc.full.wallclock").last + loopback.get("system.gc.young.wallclock").last + (loopback.get("system.gc.full.wallclock").last + loopback.get("system.gc.young.wallclock").last) / 1000.0 end end end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index f786b85925..892baceeb2 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -1,7 +1,7 @@ begin require 'ruby-prof' rescue LoadError - $stderr.puts "Specify ruby-prof as application's dependency in Gemfile to run benchmarks." + $stderr.puts 'Specify ruby-prof as application\'s dependency in Gemfile to run benchmarks.' exit end diff --git a/activesupport/lib/active_support/testing/performance/ruby/mri.rb b/activesupport/lib/active_support/testing/performance/ruby/mri.rb index d12482b58f..5fa0269b6a 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/mri.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/mri.rb @@ -19,7 +19,7 @@ module ActiveSupport # Ruby 1.8 + ruby-prof wrapper if RubyProf.respond_to?(:measure_memory) def measure - RubyProf.measure_memory / 1024.0 + RubyProf.measure_memory end end end @@ -48,7 +48,7 @@ module ActiveSupport # Ruby 1.8 + ruby-prof wrapper if RubyProf.respond_to?(:measure_gc_time) def measure - RubyProf.measure_gc_time / 1000 + RubyProf.measure_gc_time / 1000.0 / 1000.0 end end end diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb index 1e6fa2f289..d226e75d0d 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb @@ -20,7 +20,7 @@ module ActiveSupport # Ruby 1.9 + GCdata patch if GC.respond_to?(:malloc_allocated_size) def measure - GC.malloc_allocated_size / 1024.0 + GC.malloc_allocated_size end end end -- cgit v1.2.3 From 3872cc4a739db7e0fb5b4a910be371c048667ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Sat, 26 Mar 2011 03:10:00 +0000 Subject: added support for profiling under rubinius --- .../lib/active_support/testing/performance.rb | 9 ++-- .../active_support/testing/performance/rubinius.rb | 58 +++++++++++++++++++++- .../lib/active_support/testing/performance/ruby.rb | 6 +++ 3 files changed, 66 insertions(+), 7 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 9a759433b9..bba05d0a51 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -6,9 +6,10 @@ require 'action_view/helpers/number_helper' module ActiveSupport module Testing - module Performance + module Performance + # modified by each implementation DEFAULTS = - if benchmark = ARGV.include?('--benchmark') # HAX for rake test + if ARGV.include?('--benchmark') # HAX for rake test { :benchmark => true, :runs => 4, :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time], @@ -17,10 +18,8 @@ module ActiveSupport { :benchmark => false, :runs => 1, :min_percent => 0.01, - :metrics => [:process_time, :memory, :objects], - :formats => [:flat, :graph_html, :call_tree], :output => 'tmp/performance' } - end.freeze + end def self.included(base) base.superclass_delegating_accessor :profile_options diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index b9c7061571..8f1047381b 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -3,16 +3,70 @@ require 'rubinius/agent' module ActiveSupport module Testing module Performance + if !ARGV.include?('--benchmark') + DEFAULTS.merge!( + { :metrics => [:wall_time], + :formats => [:flat, :graph] }) + end + protected def run_gc GC.run(true) end + + class Performer; end + + class Profiler < Performer + def initialize(*args) + super + end + + def run + @profiler = Rubinius::Profiler::Instrumenter.new + + @profiler.profile(false) do + profile_options[:runs].to_i.times { run_test(@metric, :profile) } + end + + @total = @profiler.info[:runtime] / 1000 / 1000 / 1000.0 # seconds + end + + def report + super + end + + def record + if(profile_options[:formats].include?(:flat)) + File.open(output_filename('FlatPrinter'), 'wb') do |file| + @profiler.show(file) + end + end + + if(profile_options[:formats].include?(:graph)) + @profiler.set_options({:graph => true}) + File.open(output_filename('GraphPrinter'), 'wb') do |file| + @profiler.show(file) + end + end + end + + protected + def output_filename(printer) + suffix = + case printer + when 'FlatPrinter'; 'flat.txt' + when 'GraphPrinter'; 'graph.txt' + else printer.sub(/Printer$/, '').underscore + end + + "#{super()}_#{suffix}" + end + end module Metrics class Base attr_reader :loopback - - # TODO + def profile yield end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index 892baceeb2..13dfebbece 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -8,6 +8,12 @@ end module ActiveSupport module Testing module Performance + if !ARGV.include?('--benchmark') + DEFAULTS.merge!( + { :metrics => [:process_time, :memory, :objects], + :formats => [:flat, :graph_html, :call_tree] }) + end + protected def run_gc GC.start -- cgit v1.2.3 From 84fe2b8b4266f5ef4e3e5f2880a18b8e44a070f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Sat, 26 Mar 2011 19:12:04 +0000 Subject: added basic structure for jruby --- .../lib/active_support/testing/performance.rb | 9 ++- .../active_support/testing/performance/jruby.rb | 70 ++++++++++++++++++++++ .../active_support/testing/performance/rubinius.rb | 7 +-- 3 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 activesupport/lib/active_support/testing/performance/jruby.rb (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index bba05d0a51..0472f44a20 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -111,6 +111,10 @@ module ActiveSupport # overridden by each implementation class Profiler < Performer + def initialize(*args) + super + end + def run; end def report; end def record; end @@ -272,8 +276,9 @@ end RUBY_ENGINE = 'ruby' unless defined?(RUBY_ENGINE) # mri 1.8 case RUBY_ENGINE - when 'ruby' then require 'active_support/testing/performance/ruby' - when 'rbx' then require 'active_support/testing/performance/rubinius' + when 'ruby' then require 'active_support/testing/performance/ruby' + when 'rbx' then require 'active_support/testing/performance/rubinius' + when 'jruby' then require 'active_support/testing/performance/jruby' else $stderr.puts 'Your ruby interpreter is not supported for benchmarking.' exit diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb new file mode 100644 index 0000000000..5985e942f1 --- /dev/null +++ b/activesupport/lib/active_support/testing/performance/jruby.rb @@ -0,0 +1,70 @@ +module ActiveSupport + module Testing + module Performance + protected + def run_gc + GC.start + end + + class Performer; end + + class Profiler < Performer + def run + end + + def report + end + + def record + end + + protected + def output_filename(printer_class) + end + end + + module Metrics + class Base + def profile + end + + protected + def with_gc_stats + end + + class Time < Base; end + + class ProcessTime < Time + def measure; 0; end + end + + class WallTime < Time + def measure + super + end + end + + class CpuTime < Time + def measure; 0; end + end + + class Memory < Base + def measure; 0; end + end + + class Objects < Amount + def measure; 0; end + end + + class GcRuns < Amount + def measure; 0; end + end + + class GcTime < Time + def measure; 0; end + end + end + end + end + end +end diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index 8f1047381b..c8813a22df 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -16,11 +16,7 @@ module ActiveSupport class Performer; end - class Profiler < Performer - def initialize(*args) - super - end - + class Profiler < Performer def run @profiler = Rubinius::Profiler::Instrumenter.new @@ -72,7 +68,6 @@ module ActiveSupport end protected - # overridden by each implementation def with_gc_stats @loopback = Rubinius::Agent.loopback GC.run(true) -- cgit v1.2.3 From 93a583eb184f0e3ba21adeab789c7d441ab98a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 00:32:21 +0100 Subject: :min_percent only makes sense in a RubyProf context --- activesupport/lib/active_support/testing/performance.rb | 1 - activesupport/lib/active_support/testing/performance/ruby.rb | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 0472f44a20..ec11c60534 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -17,7 +17,6 @@ module ActiveSupport else { :benchmark => false, :runs => 1, - :min_percent => 0.01, :output => 'tmp/performance' } end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index 13dfebbece..dc77f22ba2 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -10,7 +10,8 @@ module ActiveSupport module Performance if !ARGV.include?('--benchmark') DEFAULTS.merge!( - { :metrics => [:process_time, :memory, :objects], + { :min_percent => 0.01, + :metrics => [:process_time, :memory, :objects], :formats => [:flat, :graph_html, :call_tree] }) end -- cgit v1.2.3 From 15bff5a86e916ee250f800b7c67d79fed9d5757b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 00:33:07 +0100 Subject: fix a bug where the GC wasn't being triggered at the start of the MRI benchmarks --- activesupport/lib/active_support/testing/performance/ruby/mri.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/ruby/mri.rb b/activesupport/lib/active_support/testing/performance/ruby/mri.rb index 5fa0269b6a..512eff30e2 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/mri.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/mri.rb @@ -8,6 +8,7 @@ module ActiveSupport if GC.respond_to?(:enable_stats) def with_gc_stats GC.enable_stats + GC.start yield ensure GC.disable_stats -- cgit v1.2.3 From ef988e12d8dc4fb82f46f953cac8ad64bbc08c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 00:33:36 +0100 Subject: removed duplication in rubinius' benchmark code --- .../active_support/testing/performance/rubinius.rb | 24 +++++++++------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index c8813a22df..67d21e2a43 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -13,8 +13,8 @@ module ActiveSupport def run_gc GC.run(true) end - - class Performer; end + + class Performer; end class Profiler < Performer def run @@ -33,29 +33,25 @@ module ActiveSupport def record if(profile_options[:formats].include?(:flat)) - File.open(output_filename('FlatPrinter'), 'wb') do |file| + create_path_and_open_file(:flat) do |file| @profiler.show(file) end end if(profile_options[:formats].include?(:graph)) - @profiler.set_options({:graph => true}) - File.open(output_filename('GraphPrinter'), 'wb') do |file| + create_path_and_open_file(:graph) do |file| @profiler.show(file) end end end protected - def output_filename(printer) - suffix = - case printer - when 'FlatPrinter'; 'flat.txt' - when 'GraphPrinter'; 'graph.txt' - else printer.sub(/Printer$/, '').underscore - end - - "#{super()}_#{suffix}" + def create_path_and_open_file(printer_name) + fname = "#{output_filename}_#{printer_name}.txt" + FileUtils.mkdir_p(fname) + File.open(fname, 'wb') do |file| + yield(file) + end end end -- cgit v1.2.3 From e17f60879782b3b0d8a4bc2444e1d024c65ec59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 01:32:32 +0100 Subject: warn the user about unsupported benchmarking metrics he might have asked for --- activesupport/lib/active_support/testing/performance.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index ec11c60534..6a0fc9af35 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -12,7 +12,6 @@ module ActiveSupport if ARGV.include?('--benchmark') # HAX for rake test { :benchmark => true, :runs => 4, - :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time], :output => 'tmp/performance' } else { :benchmark => false, @@ -41,6 +40,8 @@ module ActiveSupport if klass = Metrics[metric_name.to_sym] run_profile(klass.new) result.add_run + else + puts '%20s: unsupported' % metric_name end end end -- cgit v1.2.3 From e6cb3962bb51aa1f91487117b99e660cc2c43e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 01:32:56 +0100 Subject: benchmarking metrics are also implementation-specific --- .../lib/active_support/testing/performance/jruby.rb | 16 ++++++++++++++-- .../lib/active_support/testing/performance/rubinius.rb | 4 +++- .../lib/active_support/testing/performance/ruby.rb | 4 +++- 3 files changed, 20 insertions(+), 4 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb index 5985e942f1..51c716ef4a 100644 --- a/activesupport/lib/active_support/testing/performance/jruby.rb +++ b/activesupport/lib/active_support/testing/performance/jruby.rb @@ -1,9 +1,21 @@ +require 'jruby/profiler' +require 'java' +import java.lang.management.ManagementFactory + module ActiveSupport module Testing - module Performance + module Performance + if ARGV.include?('--benchmark') + DEFAULTS.merge!({:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time, :ola]}) + else + DEFAULTS.merge!( + { :metrics => [:wall_time], + :formats => [:flat, :graph] }) + end + protected def run_gc - GC.start + ManagementFactory.memory_mx_bean.gc end class Performer; end diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index 67d21e2a43..bdbb530b37 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -3,7 +3,9 @@ require 'rubinius/agent' module ActiveSupport module Testing module Performance - if !ARGV.include?('--benchmark') + if ARGV.include?('--benchmark') + DEFAULTS.merge!({:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]}) + else DEFAULTS.merge!( { :metrics => [:wall_time], :formats => [:flat, :graph] }) diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index dc77f22ba2..b36b201531 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -8,7 +8,9 @@ end module ActiveSupport module Testing module Performance - if !ARGV.include?('--benchmark') + if ARGV.include?('--benchmark') + DEFAULTS.merge!({:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]}) + else DEFAULTS.merge!( { :min_percent => 0.01, :metrics => [:process_time, :memory, :objects], -- cgit v1.2.3 From d6d059f2807f3cf3d29652b02d5940abd4561bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 01:33:43 +0100 Subject: added profiling and benchmarking capabilities to jruby (profiling is crippled because of a jruby bug) --- .../active_support/testing/performance/jruby.rb | 71 ++++++++++++++++------ 1 file changed, 53 insertions(+), 18 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb index 51c716ef4a..6d94dacdd6 100644 --- a/activesupport/lib/active_support/testing/performance/jruby.rb +++ b/activesupport/lib/active_support/testing/performance/jruby.rb @@ -6,7 +6,7 @@ module ActiveSupport module Testing module Performance if ARGV.include?('--benchmark') - DEFAULTS.merge!({:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time, :ola]}) + DEFAULTS.merge!({:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time]}) else DEFAULTS.merge!( { :metrics => [:wall_time], @@ -22,33 +22,59 @@ module ActiveSupport class Profiler < Performer def run + @data = JRuby::Profiler.profile do + profile_options[:runs].to_i.times { run_test(@metric, :profile) } + end + + profile_printer = JRuby::Profiler::GraphProfilePrinter.new(@data) + profile_printer.printProfile(STDOUT) + + @total = @data.getDuration / 1000 / 1000 / 1000.0 # seconds end - + def report + super end - + def record + klasses = profile_options[:formats].map { |f| JRuby::Profiler.const_get("#{f.to_s.camelize}ProfilePrinter") }.compact + + klasses.each do |klass| + fname = output_filename(klass) + FileUtils.mkdir_p(File.dirname(fname)) + file = File.open(fname, 'wb') do |file| + klass.new(@data).printProfile(file) + end + end end - + protected def output_filename(printer_class) + suffix = + case printer_class.name.demodulize + when 'FlatProfilePrinter'; 'flat.txt' + when 'GraphProfilePrinter'; 'graph.txt' + else printer_class.name.sub(/ProfilePrinter$/, '').underscore + end + + "#{super()}_#{suffix}" end end module Metrics class Base def profile + yield end protected def with_gc_stats + ManagementFactory.memory_mx_bean.gc + yield end + end class Time < Base; end - - class ProcessTime < Time - def measure; 0; end - end class WallTime < Time def measure @@ -57,24 +83,33 @@ module ActiveSupport end class CpuTime < Time - def measure; 0; end + def measure + ManagementFactory.thread_mx_bean.get_current_thread_cpu_time / 1000 / 1000 / 1000.0 # seconds + end end - - class Memory < Base - def measure; 0; end + + class UserTime < Time + def measure + ManagementFactory.thread_mx_bean.get_current_thread_user_time / 1000 / 1000 / 1000.0 # seconds + end end - class Objects < Amount - def measure; 0; end + class Memory < Base + def measure + ManagementFactory.memory_mx_bean.non_heap_memory_usage.used + ManagementFactory.memory_mx_bean.heap_memory_usage.used + end end - + class GcRuns < Amount - def measure; 0; end + def measure + ManagementFactory.garbage_collector_mx_beans.inject(0) { |total_runs, current_gc| total_runs += current_gc.collection_count } + end end class GcTime < Time - def measure; 0; end - end + def measure + ManagementFactory.garbage_collector_mx_beans.inject(0) { |total_time, current_gc| total_time += current_gc.collection_time } / 1000.0 # seconds + end end end end -- cgit v1.2.3 From 983bd01f42a9a3f106c27b37b1074c648263e861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 03:08:08 +0100 Subject: we need test-unit on mri 1.9 --- .../lib/active_support/testing/performance/ruby/yarv.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb index d226e75d0d..ed2b8d6803 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb @@ -1,3 +1,10 @@ +begin + require 'test-unit' +rescue LoadError + $stderr.puts 'Specify test-unit as application\'s dependency in Gemfile to run benchmarks.' + exit +end + module ActiveSupport module Testing module Performance @@ -57,6 +64,3 @@ module ActiveSupport end end end - - - -- cgit v1.2.3 From c401ad98536b8038bf20f000b41e3f185de0ab7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 03:11:42 +0100 Subject: improved options handling in performance tests --- .../lib/active_support/testing/performance.rb | 25 ++++++++++++---------- .../active_support/testing/performance/jruby.rb | 16 +++++++------- .../active_support/testing/performance/rubinius.rb | 18 ++++++++-------- .../lib/active_support/testing/performance/ruby.rb | 22 +++++++++---------- 4 files changed, 42 insertions(+), 39 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 6a0fc9af35..3195750841 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -7,7 +7,7 @@ require 'action_view/helpers/number_helper' module ActiveSupport module Testing module Performance - # modified by each implementation + # each implementation should define metrics and freeze the defaults DEFAULTS = if ARGV.include?('--benchmark') # HAX for rake test { :benchmark => true, @@ -21,13 +21,16 @@ module ActiveSupport def self.included(base) base.superclass_delegating_accessor :profile_options - base.profile_options = DEFAULTS + end + + def full_profile_options + DEFAULTS.merge(profile_options) end def full_test_name "#{self.class.name}##{method_name}" end - + def run(result) return if method_name =~ /^default_test$/ @@ -35,13 +38,13 @@ module ActiveSupport @_result = result run_warmup - if profile_options && metrics = profile_options[:metrics] + if full_profile_options && metrics = full_profile_options[:metrics] metrics.each do |metric_name| if klass = Metrics[metric_name.to_sym] run_profile(klass.new) result.add_run else - puts '%20s: unsupported' % metric_name + puts '%20s: unsupported' % @metric.name end end end @@ -83,7 +86,7 @@ module ActiveSupport end def run_profile(metric) - klass = profile_options[:benchmark] ? Benchmarker : Profiler + klass = full_profile_options[:benchmark] ? Benchmarker : Profiler performer = klass.new(self, metric) performer.run @@ -92,20 +95,20 @@ module ActiveSupport end class Performer - delegate :run_test, :profile_options, :full_test_name, :to => :@harness + delegate :run_test, :full_profile_options, :full_test_name, :to => :@harness def initialize(harness, metric) @harness, @metric = harness, metric end def report - rate = @total / profile_options[:runs] + rate = @total / full_profile_options[:runs] '%20s: %s' % [@metric.name, @metric.format(rate)] end protected def output_filename - "#{profile_options[:output]}/#{full_test_name}_#{@metric.name}" + "#{full_profile_options[:output]}/#{full_test_name}_#{@metric.name}" end end @@ -122,12 +125,12 @@ module ActiveSupport class Benchmarker < Performer def run - profile_options[:runs].to_i.times { run_test(@metric, :benchmark) } + full_profile_options[:runs].to_i.times { run_test(@metric, :benchmark) } @total = @metric.total end def record - avg = @metric.total / profile_options[:runs].to_i + avg = @metric.total / full_profile_options[:runs].to_i now = Time.now.utc.xmlschema with_output_file do |file| file.puts "#{avg},#{now},#{environment}" diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb index 6d94dacdd6..e489c1f0dd 100644 --- a/activesupport/lib/active_support/testing/performance/jruby.rb +++ b/activesupport/lib/active_support/testing/performance/jruby.rb @@ -5,13 +5,13 @@ import java.lang.management.ManagementFactory module ActiveSupport module Testing module Performance - if ARGV.include?('--benchmark') - DEFAULTS.merge!({:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time]}) - else - DEFAULTS.merge!( + DEFAULTS.merge!( + if ARGV.include?('--benchmark') + {:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time]} + else { :metrics => [:wall_time], - :formats => [:flat, :graph] }) - end + :formats => [:flat, :graph] } + end).freeze protected def run_gc @@ -23,7 +23,7 @@ module ActiveSupport class Profiler < Performer def run @data = JRuby::Profiler.profile do - profile_options[:runs].to_i.times { run_test(@metric, :profile) } + full_profile_options[:runs].to_i.times { run_test(@metric, :profile) } end profile_printer = JRuby::Profiler::GraphProfilePrinter.new(@data) @@ -37,7 +37,7 @@ module ActiveSupport end def record - klasses = profile_options[:formats].map { |f| JRuby::Profiler.const_get("#{f.to_s.camelize}ProfilePrinter") }.compact + klasses = full_profile_options[:formats].map { |f| JRuby::Profiler.const_get("#{f.to_s.camelize}ProfilePrinter") }.compact klasses.each do |klass| fname = output_filename(klass) diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index bdbb530b37..55b142e20c 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -3,13 +3,13 @@ require 'rubinius/agent' module ActiveSupport module Testing module Performance - if ARGV.include?('--benchmark') - DEFAULTS.merge!({:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]}) - else - DEFAULTS.merge!( + DEFAULTS.merge!( + if ARGV.include?('--benchmark') + {:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]} + else { :metrics => [:wall_time], - :formats => [:flat, :graph] }) - end + :formats => [:flat, :graph] } + end).freeze protected def run_gc @@ -23,7 +23,7 @@ module ActiveSupport @profiler = Rubinius::Profiler::Instrumenter.new @profiler.profile(false) do - profile_options[:runs].to_i.times { run_test(@metric, :profile) } + full_profile_options[:runs].to_i.times { run_test(@metric, :profile) } end @total = @profiler.info[:runtime] / 1000 / 1000 / 1000.0 # seconds @@ -34,13 +34,13 @@ module ActiveSupport end def record - if(profile_options[:formats].include?(:flat)) + if(full_profile_options[:formats].include?(:flat)) create_path_and_open_file(:flat) do |file| @profiler.show(file) end end - if(profile_options[:formats].include?(:graph)) + if(full_profile_options[:formats].include?(:graph)) create_path_and_open_file(:graph) do |file| @profiler.show(file) end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index b36b201531..a8b26b85eb 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -8,14 +8,14 @@ end module ActiveSupport module Testing module Performance - if ARGV.include?('--benchmark') - DEFAULTS.merge!({:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]}) - else - DEFAULTS.merge!( + DEFAULTS.merge!( + if ARGV.include?('--benchmark') + ({:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]} + else { :min_percent => 0.01, :metrics => [:process_time, :memory, :objects], - :formats => [:flat, :graph_html, :call_tree] }) - end + :formats => [:flat, :graph_html, :call_tree] } + end).freeze protected def run_gc @@ -36,7 +36,7 @@ module ActiveSupport RubyProf.measure_mode = @metric.measure_mode RubyProf.start RubyProf.pause - profile_options[:runs].to_i.times { run_test(@metric, :profile) } + full_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 @@ -52,13 +52,13 @@ module ActiveSupport def record return unless @supported - klasses = profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact + klasses = full_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)) + klass.new(@data).print(file, full_profile_options.slice(:min_percent)) end end end @@ -166,9 +166,9 @@ module ActiveSupport end end -if RUBY_VERSION >= '1.9.2' +if RUBY_VERSION.between?('1.9.2', '2.0') require 'active_support/testing/performance/ruby/yarv' -elsif RUBY_VERSION >= '1.8.6' +elsif RUBY_VERSION.between?('1.8.6', '1.9') require 'active_support/testing/performance/ruby/mri' else $stderr.puts 'Update your ruby interpreter to be able to run benchmarks.' -- cgit v1.2.3 From 09bd0eeefc5cb3c2cb26e17b486dd0965afbf4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 04:03:47 +0100 Subject: fixed a couple of hidden bugs --- activesupport/lib/active_support/testing/performance.rb | 3 ++- activesupport/lib/active_support/testing/performance/ruby.rb | 2 +- activesupport/lib/active_support/testing/performance/ruby/yarv.rb | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 3195750841..495fcea381 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -21,6 +21,7 @@ module ActiveSupport def self.included(base) base.superclass_delegating_accessor :profile_options + base.profile_options = {} end def full_profile_options @@ -44,7 +45,7 @@ module ActiveSupport run_profile(klass.new) result.add_run else - puts '%20s: unsupported' % @metric.name + puts '%20s: unsupported' % metric_name end end end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index a8b26b85eb..36dc75ca8f 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -10,7 +10,7 @@ module ActiveSupport module Performance DEFAULTS.merge!( if ARGV.include?('--benchmark') - ({:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]} + {:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]} else { :min_percent => 0.01, :metrics => [:process_time, :memory, :objects], diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb index ed2b8d6803..38b6e67767 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb @@ -1,5 +1,5 @@ begin - require 'test-unit' + gem 'test-unit' rescue LoadError $stderr.puts 'Specify test-unit as application\'s dependency in Gemfile to run benchmarks.' exit -- cgit v1.2.3 From 726b7ede54031eecfcee34eec80040553e9ad19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 28 Mar 2011 04:19:39 +0100 Subject: improved detection and feedback of supported/unsupported metrics --- .../lib/active_support/testing/performance.rb | 35 ++-------------------- .../active_support/testing/performance/jruby.rb | 4 +-- .../active_support/testing/performance/rubinius.rb | 14 +-------- .../lib/active_support/testing/performance/ruby.rb | 4 +-- .../active_support/testing/performance/ruby/mri.rb | 2 +- .../testing/performance/ruby/yarv.rb | 2 +- 6 files changed, 7 insertions(+), 54 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 495fcea381..f6945e8466 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -235,44 +235,13 @@ module ActiveSupport end end - class ProcessTime < Time - # overridden by each implementation - def measure; end - end - - class WallTime < Time - # overridden by each implementation - def measure; end - end - - class CpuTime < Time - # overridden by each implementation - def measure; end - end - - class Memory < Base - # overridden by each implementation - def measure; end - + class DigitalInformationUnit < Base def format(measurement) number_to_human_size(measurement, :precision => 2) end end - class Objects < Amount - # overridden by each implementation - def measure; end - end - - class GcRuns < Amount - # overridden by each implementation - def measure; end - end - - class GcTime < Time - # overridden by each implementation - def measure; end - end + # each implementation provides its own metrics like ProcessTime, Memory or GcRuns end end end diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb index e489c1f0dd..b76c11f12b 100644 --- a/activesupport/lib/active_support/testing/performance/jruby.rb +++ b/activesupport/lib/active_support/testing/performance/jruby.rb @@ -73,8 +73,6 @@ module ActiveSupport yield end end - - class Time < Base; end class WallTime < Time def measure @@ -94,7 +92,7 @@ module ActiveSupport end end - class Memory < Base + class Memory < DigitalInformationUnit def measure ManagementFactory.memory_mx_bean.non_heap_memory_usage.used + ManagementFactory.memory_mx_bean.heap_memory_usage.used end diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index 55b142e20c..a0511f42ed 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -72,13 +72,6 @@ module ActiveSupport yield end end - - class Time < Base; end - - class ProcessTime < Time - # unsupported - def measure; 0; end - end class WallTime < Time def measure @@ -86,12 +79,7 @@ module ActiveSupport end end - class CpuTime < Time - # unsupported - def measure; 0; end - end - - class Memory < Base + class Memory < DigitalInformationUnit def measure loopback.get("system.memory.counter.bytes").last end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index 36dc75ca8f..d08eedc653 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -102,8 +102,6 @@ module ActiveSupport end end - class Time < Base; end - class ProcessTime < Time Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME) @@ -134,7 +132,7 @@ module ActiveSupport end end - class Memory < Base + class Memory < DigitalInformationUnit Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY) # overridden by each implementation diff --git a/activesupport/lib/active_support/testing/performance/ruby/mri.rb b/activesupport/lib/active_support/testing/performance/ruby/mri.rb index 512eff30e2..22c31927f0 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/mri.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/mri.rb @@ -16,7 +16,7 @@ module ActiveSupport end end - class Memory < Base + class Memory < DigitalInformationUnit # Ruby 1.8 + ruby-prof wrapper if RubyProf.respond_to?(:measure_memory) def measure diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb index 38b6e67767..dcbea17a22 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb @@ -23,7 +23,7 @@ module ActiveSupport end end - class Memory < Base + class Memory < DigitalInformationUnit # Ruby 1.9 + GCdata patch if GC.respond_to?(:malloc_allocated_size) def measure -- cgit v1.2.3 From a35ba6cf5a91b0cde0a22007f8532313754d0cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Tue, 29 Mar 2011 23:43:26 +0100 Subject: don't allow decimal places on the amount of objects and gc runs --- activesupport/lib/active_support/testing/performance.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index f6945e8466..71d49459ef 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -231,7 +231,7 @@ module ActiveSupport class Amount < Base def format(measurement) - number_with_delimiter(measurement) + number_with_delimiter(measurement.floor) end end -- cgit v1.2.3 From 391ccdaf35f41e38905a940a72e30b484cb0baf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Wed, 30 Mar 2011 00:00:26 +0100 Subject: fixed a bug where rubinius was creating the profiling files as directories --- activesupport/lib/active_support/testing/performance/rubinius.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index a0511f42ed..547b7cf048 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -50,7 +50,7 @@ module ActiveSupport protected def create_path_and_open_file(printer_name) fname = "#{output_filename}_#{printer_name}.txt" - FileUtils.mkdir_p(fname) + FileUtils.mkdir_p(File.dirname(fname)) File.open(fname, 'wb') do |file| yield(file) end -- cgit v1.2.3 From 09cdd1cac149cf8e18f16e39937d659146e61f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Wed, 30 Mar 2011 03:23:16 +0100 Subject: check if there is support for the specified metric when profiling --- .../lib/active_support/testing/performance.rb | 18 ++++++++++++------ .../lib/active_support/testing/performance/jruby.rb | 15 ++++++++++----- .../lib/active_support/testing/performance/rubinius.rb | 15 ++++++++++----- .../lib/active_support/testing/performance/ruby.rb | 8 -------- 4 files changed, 32 insertions(+), 24 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 71d49459ef..5e9bc40976 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -10,12 +10,10 @@ module ActiveSupport # each implementation should define metrics and freeze the defaults DEFAULTS = if ARGV.include?('--benchmark') # HAX for rake test - { :benchmark => true, - :runs => 4, + { :runs => 4, :output => 'tmp/performance' } else - { :benchmark => false, - :runs => 1, + { :runs => 1, :output => 'tmp/performance' } end @@ -87,7 +85,7 @@ module ActiveSupport end def run_profile(metric) - klass = full_profile_options[:benchmark] ? Benchmarker : Profiler + klass = ARGV.include?('--benchmark') ? Benchmarker : Profiler performer = klass.new(self, metric) performer.run @@ -117,10 +115,18 @@ module ActiveSupport class Profiler < Performer def initialize(*args) super + @supported = false + end + + def report + if @supported + super + else + '%20s: unsupported' % @metric.name + end end def run; end - def report; end def record; end end diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb index b76c11f12b..6993db1a3b 100644 --- a/activesupport/lib/active_support/testing/performance/jruby.rb +++ b/activesupport/lib/active_support/testing/performance/jruby.rb @@ -10,7 +10,7 @@ module ActiveSupport {:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time]} else { :metrics => [:wall_time], - :formats => [:flat, :graph] } + :formats => [:flat, :graph] } end).freeze protected @@ -21,7 +21,14 @@ module ActiveSupport class Performer; end class Profiler < Performer + def initialize(*args) + super + @supported = @metric.is_a?(Metrics::WallTime) + end + def run + return unless @supported + @data = JRuby::Profiler.profile do full_profile_options[:runs].to_i.times { run_test(@metric, :profile) } end @@ -32,11 +39,9 @@ module ActiveSupport @total = @data.getDuration / 1000 / 1000 / 1000.0 # seconds end - def report - super - end - def record + return unless @supported + klasses = full_profile_options[:formats].map { |f| JRuby::Profiler.const_get("#{f.to_s.camelize}ProfilePrinter") }.compact klasses.each do |klass| diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index 547b7cf048..b2e77b3ce9 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -18,8 +18,15 @@ module ActiveSupport class Performer; end - class Profiler < Performer + class Profiler < Performer + def initialize(*args) + super + @supported = @metric.is_a?(Metrics::WallTime) + end + def run + return unless @supported + @profiler = Rubinius::Profiler::Instrumenter.new @profiler.profile(false) do @@ -29,11 +36,9 @@ module ActiveSupport @total = @profiler.info[:runtime] / 1000 / 1000 / 1000.0 # seconds end - def report - super - end - def record + return unless @supported + if(full_profile_options[:formats].include?(:flat)) create_path_and_open_file(:flat) do |file| @profiler.show(file) diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index d08eedc653..e887af1979 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -41,14 +41,6 @@ module ActiveSupport @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 -- cgit v1.2.3 From 677ce63d92b7725b0a11facddc1ba95f50f865df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Sun, 3 Apr 2011 01:09:34 +0100 Subject: profiling enabled under JRuby. Added documentation for workaround described in JRUBY-5650. --- activesupport/lib/active_support/testing/performance/jruby.rb | 7 +------ .../lib/active_support/testing/performance/rubinius.rb | 6 +++--- activesupport/lib/active_support/testing/performance/ruby.rb | 10 ++++------ .../lib/active_support/testing/performance/ruby/mri.rb | 2 -- 4 files changed, 8 insertions(+), 17 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb index 6993db1a3b..9beadba310 100644 --- a/activesupport/lib/active_support/testing/performance/jruby.rb +++ b/activesupport/lib/active_support/testing/performance/jruby.rb @@ -16,9 +16,7 @@ module ActiveSupport protected def run_gc ManagementFactory.memory_mx_bean.gc - end - - class Performer; end + end class Profiler < Performer def initialize(*args) @@ -33,9 +31,6 @@ module ActiveSupport full_profile_options[:runs].to_i.times { run_test(@metric, :profile) } end - profile_printer = JRuby::Profiler::GraphProfilePrinter.new(@data) - profile_printer.printProfile(STDOUT) - @total = @data.getDuration / 1000 / 1000 / 1000.0 # seconds end diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index b2e77b3ce9..fafa782e8d 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -84,19 +84,19 @@ module ActiveSupport end end - class Memory < DigitalInformationUnit + class Memory < DigitalInformationUnit def measure loopback.get("system.memory.counter.bytes").last end end - class Objects < Amount + class Objects < Amount def measure loopback.get("system.memory.counter.objects").last end end - class GcRuns < Amount + class GcRuns < Amount def measure loopback.get("system.gc.full.count").last + loopback.get("system.gc.young.count").last end diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index e887af1979..0d40dcd22a 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -21,8 +21,6 @@ module ActiveSupport def run_gc GC.start end - - class Performer; end class Profiler < Performer def initialize(*args) @@ -128,28 +126,28 @@ module ActiveSupport Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY) # overridden by each implementation - def measure; 0; end + def measure; end end class Objects < Amount Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS) # overridden by each implementation - def measure; 0; end + def measure; end end class GcRuns < Amount Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS) # overridden by each implementation - def measure; 0; end + def measure; end end class GcTime < Time Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME) # overridden by each implementation - def measure; 0; end + def measure; end end end end diff --git a/activesupport/lib/active_support/testing/performance/ruby/mri.rb b/activesupport/lib/active_support/testing/performance/ruby/mri.rb index 22c31927f0..86e650050b 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/mri.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/mri.rb @@ -24,8 +24,6 @@ module ActiveSupport end end end - - class Amount < Base; end class Objects < Amount # Ruby 1.8 + ruby-prof wrapper -- cgit v1.2.3 From 65022acda0d407b28249988ab2c715d2a8256702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Sun, 3 Apr 2011 02:09:53 +0100 Subject: removed unused class declaration --- activesupport/lib/active_support/testing/performance/ruby/yarv.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb index dcbea17a22..ad0e882214 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb @@ -31,8 +31,6 @@ module ActiveSupport end end end - - class Amount < Base; end class Objects < Amount # Ruby 1.9 + GCdata patch -- cgit v1.2.3 From 8d558cb1b069410c8f693295c9c4e2ffc9661e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Sun, 3 Apr 2011 03:16:35 +0100 Subject: don't use internal profiler methods on Rubinius and JRuby since we're only measuring wall clock for now (and the APIs will/can change, respectively) --- activesupport/lib/active_support/testing/performance.rb | 6 ++++++ activesupport/lib/active_support/testing/performance/jruby.rb | 8 ++++---- activesupport/lib/active_support/testing/performance/rubinius.rb | 8 ++++---- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 5e9bc40976..598eb330eb 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -126,6 +126,12 @@ module ActiveSupport end end + def time_with_block + before = Time.now + yield + Time.now - before + end + def run; end def record; end end diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb index 9beadba310..6b27959840 100644 --- a/activesupport/lib/active_support/testing/performance/jruby.rb +++ b/activesupport/lib/active_support/testing/performance/jruby.rb @@ -27,11 +27,11 @@ module ActiveSupport def run return unless @supported - @data = JRuby::Profiler.profile do - full_profile_options[:runs].to_i.times { run_test(@metric, :profile) } + @total = time_with_block do + @data = JRuby::Profiler.profile do + full_profile_options[:runs].to_i.times { run_test(@metric, :profile) } + end end - - @total = @data.getDuration / 1000 / 1000 / 1000.0 # seconds end def record diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index fafa782e8d..fbb58a2b3a 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -29,11 +29,11 @@ module ActiveSupport @profiler = Rubinius::Profiler::Instrumenter.new - @profiler.profile(false) do - full_profile_options[:runs].to_i.times { run_test(@metric, :profile) } + @total = time_with_block do + @profiler.profile(false) do + full_profile_options[:runs].to_i.times { run_test(@metric, :profile) } + end end - - @total = @profiler.info[:runtime] / 1000 / 1000 / 1000.0 # seconds end def record -- cgit v1.2.3 From 181c8422d776bb85cb18a7023d3524307a31417c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Sun, 8 May 2011 04:20:14 +0100 Subject: explicitly return from run() under minitest (metrics were printed with the previous solution) --- activesupport/lib/active_support/testing/performance.rb | 2 ++ activesupport/lib/active_support/testing/performance/ruby.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 4db59680b0..4e58b6a564 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -51,6 +51,8 @@ module ActiveSupport end end end + + return end def run_test(metric, mode) diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index 0d40dcd22a..3dc668cd92 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -10,7 +10,7 @@ module ActiveSupport module Performance DEFAULTS.merge!( if ARGV.include?('--benchmark') - {:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]} + { :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time] } else { :min_percent => 0.01, :metrics => [:process_time, :memory, :objects], -- cgit v1.2.3 From 0d1f7584ba25e7289871b5503f010874bc2aef49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Mon, 9 May 2011 23:29:00 +0100 Subject: contemplate unsupported metrics --- .../lib/active_support/testing/performance.rb | 34 +++++++++++----------- .../lib/active_support/testing/performance/ruby.rb | 12 -------- .../testing/performance/ruby/yarv.rb | 2 +- 3 files changed, 18 insertions(+), 30 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 4e58b6a564..b62d9b16e1 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -142,12 +142,16 @@ module ActiveSupport delegate :run_test, :full_profile_options, :full_test_name, :to => :@harness def initialize(harness, metric) - @harness, @metric = harness, metric + @harness, @metric, @supported = harness, metric, false end def report - rate = @total / full_profile_options[:runs] - '%20s: %s' % [@metric.name, @metric.format(rate)] + if @supported + rate = @total / full_profile_options[:runs] + '%20s: %s' % [@metric.name, @metric.format(rate)] + else + '%20s: unsupported' % @metric.name + end end protected @@ -158,19 +162,6 @@ module ActiveSupport # overridden by each implementation class Profiler < Performer - def initialize(*args) - super - @supported = false - end - - def report - if @supported - super - else - '%20s: unsupported' % @metric.name - end - end - def time_with_block before = Time.now yield @@ -181,8 +172,15 @@ module ActiveSupport def record; end end - class Benchmarker < Performer + class Benchmarker < Performer + def initialize(*args) + super + @supported = @metric.respond_to?('measure') + end + def run + return unless @supported + full_profile_options[:runs].to_i.times { run_test(@metric, :benchmark) } @total = @metric.total end @@ -257,6 +255,8 @@ module ActiveSupport end def benchmark + @unsureturn if measure.nil? + with_gc_stats do before = measure yield diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index 3dc668cd92..9f56a412a1 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -124,30 +124,18 @@ module ActiveSupport class Memory < DigitalInformationUnit Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY) - - # overridden by each implementation - def measure; end end class Objects < Amount Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS) - - # overridden by each implementation - def measure; end end class GcRuns < Amount Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS) - - # overridden by each implementation - def measure; end end class GcTime < Time Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME) - - # overridden by each implementation - def measure; end end end end diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb index 498bc6b4db..62095a8fe4 100644 --- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb +++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb @@ -17,7 +17,7 @@ module ActiveSupport end class Memory < DigitalInformationUnit - # Ruby 1.9 + GCdata patch + # Ruby 1.9 + GCdata patch if GC.respond_to?(:malloc_allocated_size) def measure GC.malloc_allocated_size -- cgit v1.2.3 From 810fb2b5273591ff396ae9bcc1cf78b5d575c33d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Tue, 10 May 2011 01:38:21 +0100 Subject: benchmarker and profiler now use the new performance testing tools (support for Rubinius and JRuby and high configurability) --- activesupport/lib/active_support/testing/performance.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index b62d9b16e1..4e970c034f 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -23,12 +23,15 @@ module ActiveSupport # each implementation should define metrics and freeze the defaults DEFAULTS = - if ARGV.include?('--benchmark') # HAX for rake test + if ARGV.include?('--benchmark') # HAX for rake test { :runs => 4, - :output => 'tmp/performance' } + :output => 'tmp/performance', + :benchmark => true } else + puts "not" { :runs => 1, - :output => 'tmp/performance' } + :output => 'tmp/performance', + :benchmark => false } end def full_profile_options @@ -130,7 +133,7 @@ module ActiveSupport end def run_profile(metric) - klass = ARGV.include?('--benchmark') ? Benchmarker : Profiler + klass = full_profile_options[:benchmark] ? Benchmarker : Profiler performer = klass.new(self, metric) performer.run -- cgit v1.2.3 From 0304d8076adefe63b07bbc7e9f464f99ac24ca59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Tue, 10 May 2011 02:49:32 +0100 Subject: ruby-prof's awesome call stack printer is now used by default --- activesupport/lib/active_support/testing/performance/ruby.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb index 9f56a412a1..b29ec6719c 100644 --- a/activesupport/lib/active_support/testing/performance/ruby.rb +++ b/activesupport/lib/active_support/testing/performance/ruby.rb @@ -14,7 +14,7 @@ module ActiveSupport else { :min_percent => 0.01, :metrics => [:process_time, :memory, :objects], - :formats => [:flat, :graph_html, :call_tree] } + :formats => [:flat, :graph_html, :call_tree, :call_stack] } end).freeze protected -- cgit v1.2.3 From aaa85cde6068f4db6fabe7bfef664f73bbc6938f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Tue, 10 May 2011 02:52:10 +0100 Subject: remove forgotten puts --- activesupport/lib/active_support/testing/performance.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index 4e970c034f..f0287b0440 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -28,7 +28,6 @@ module ActiveSupport :output => 'tmp/performance', :benchmark => true } else - puts "not" { :runs => 1, :output => 'tmp/performance', :benchmark => false } -- cgit v1.2.3 From 7fcf0ca69e18841be9fb0dcce2721f4ed2c8eca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Silva?= Date: Tue, 10 May 2011 03:40:44 +0100 Subject: removed redundant metric support check (and print when it isn't) --- activesupport/lib/active_support/testing/performance.rb | 6 +++--- activesupport/lib/active_support/testing/performance/rubinius.rb | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb index f0287b0440..02c19448fd 100644 --- a/activesupport/lib/active_support/testing/performance.rb +++ b/activesupport/lib/active_support/testing/performance.rb @@ -90,6 +90,8 @@ module ActiveSupport if klass = Metrics[metric_name.to_sym] run_profile(klass.new) result.add_run + else + puts '%20s: unsupported' % metric_name end end end @@ -256,9 +258,7 @@ module ActiveSupport @name ||= self.class.name.demodulize.underscore end - def benchmark - @unsureturn if measure.nil? - + def benchmark with_gc_stats do before = measure yield diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb index fbb58a2b3a..198d235548 100644 --- a/activesupport/lib/active_support/testing/performance/rubinius.rb +++ b/activesupport/lib/active_support/testing/performance/rubinius.rb @@ -84,19 +84,19 @@ module ActiveSupport end end - class Memory < DigitalInformationUnit + class Memory < DigitalInformationUnit def measure loopback.get("system.memory.counter.bytes").last end end - class Objects < Amount + class Objects < Amount def measure loopback.get("system.memory.counter.objects").last end end - class GcRuns < Amount + class GcRuns < Amount def measure loopback.get("system.gc.full.count").last + loopback.get("system.gc.young.count").last end -- cgit v1.2.3