benchmarker and profiler now use the new performance testing tools (support for Rubinius and JRuby and high configurability)
This commit is contained in:
parent
9ca97a6baf
commit
dcc99e23cd
@ -23,12 +23,14 @@ module Performance
|
||||
|
||||
# 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
|
||||
{ :runs => 1,
|
||||
:output => 'tmp/performance' }
|
||||
:output => 'tmp/performance',
|
||||
:benchmark => false }
|
||||
end
|
||||
|
||||
def full_profile_options
|
||||
@ -130,7 +132,7 @@ def run_warmup
|
||||
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
|
||||
|
@ -458,55 +458,47 @@ Writing performance test cases could be an overkill when you are looking for one
|
||||
|
||||
h4. +benchmarker+
|
||||
|
||||
+benchmarker+ is a wrapper around Ruby's "Benchmark":http://ruby-doc.org/core/classes/Benchmark.html standard library.
|
||||
|
||||
Usage:
|
||||
|
||||
<shell>
|
||||
$ rails benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ...
|
||||
Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]
|
||||
-r, --runs N Number of runs.
|
||||
Default: 4
|
||||
-o, --output PATH Directory to use when writing the results.
|
||||
Default: tmp/performance
|
||||
-m, --metrics a,b,c Metrics to use.
|
||||
Default: wall_time,memory,objects,gc_runs,gc_time
|
||||
</shell>
|
||||
|
||||
Examples:
|
||||
Example:
|
||||
|
||||
<shell>
|
||||
$ rails benchmarker 10 'Item.all' 'CouchItem.all'
|
||||
</shell>
|
||||
|
||||
If the +[times]+ argument is omitted, supplied methods are run just once:
|
||||
|
||||
<shell>
|
||||
$ rails benchmarker 'Item.first' 'Item.last'
|
||||
$ rails benchmarker 'Item.all' 'CouchItem.all' --runs 3 --metrics wall_time,memory
|
||||
</shell>
|
||||
|
||||
h4. +profiler+
|
||||
|
||||
+profiler+ is a wrapper around the "ruby-prof":http://ruby-prof.rubyforge.org gem.
|
||||
|
||||
Usage:
|
||||
|
||||
<shell>
|
||||
$ rails profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]
|
||||
Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]
|
||||
-r, --runs N Number of runs.
|
||||
Default: 1
|
||||
-o, --output PATH Directory to use when writing the results.
|
||||
Default: tmp/performance
|
||||
--metrics a,b,c Metrics to use.
|
||||
Default: process_time,memory,objects
|
||||
-m, --formats x,y,z Formats to output to.
|
||||
Default: flat,graph_html,call_tree
|
||||
</shell>
|
||||
|
||||
Examples:
|
||||
Example:
|
||||
|
||||
<shell>
|
||||
$ rails profiler 'Item.all'
|
||||
$ rails profiler 'Item.all' 'CouchItem.all' --runs 2 --metrics process_time --formats flat
|
||||
</shell>
|
||||
|
||||
This will profile +Item.all+ in +RubyProf::WALL_TIME+ measure mode. By default, it prints flat output to the shell.
|
||||
|
||||
<shell>
|
||||
$ rails profiler 'Item.all' 10 graph
|
||||
</shell>
|
||||
|
||||
This will profile +10.times { Item.all }+ with +RubyProf::WALL_TIME+ measure mode and print graph output to the shell.
|
||||
|
||||
If you want to store the output in a file:
|
||||
|
||||
<shell>
|
||||
$ rails profiler 'Item.all' 10 graph 2> graph.txt
|
||||
</shell>
|
||||
NOTE: Metrics and formats vary from interpreter to interpreter. Pass +--help+ to each tool to see the defaults for your interpreter.
|
||||
|
||||
h3. Helper Methods
|
||||
|
||||
|
@ -1,25 +1,34 @@
|
||||
require 'active_support/core_ext/object/inclusion'
|
||||
require 'optparse'
|
||||
require 'rails/test_help'
|
||||
require 'rails/performance_test_help'
|
||||
|
||||
if ARGV.first.in?([nil, "-h", "--help"])
|
||||
puts "Usage: rails benchmarker [times] 'Person.expensive_way' 'Person.another_expensive_way' ..."
|
||||
exit 1
|
||||
ARGV.push('--benchmark') # HAX
|
||||
require 'active_support/testing/performance'
|
||||
ARGV.pop
|
||||
|
||||
def options
|
||||
options = {}
|
||||
defaults = ActiveSupport::Testing::Performance::DEFAULTS
|
||||
|
||||
OptionParser.new do |opt|
|
||||
opt.banner = "Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]"
|
||||
opt.on('-r', '--runs N', Numeric, 'Number of runs.', "Default: #{defaults[:runs]}") { |r| options[:runs] = r }
|
||||
opt.on('-o', '--output PATH', String, 'Directory to use when writing the results.', "Default: #{defaults[:output]}") { |o| options[:output] = o }
|
||||
opt.on('-m', '--metrics a,b,c', Array, 'Metrics to use.', "Default: #{defaults[:metrics].join(",")}") { |m| options[:metrics] = m.map(&:to_sym) }
|
||||
opt.parse!(ARGV)
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
begin
|
||||
N = Integer(ARGV.first)
|
||||
ARGV.shift
|
||||
rescue ArgumentError
|
||||
N = 1
|
||||
end
|
||||
|
||||
require 'benchmark'
|
||||
include Benchmark
|
||||
|
||||
# Don't include compilation in the benchmark
|
||||
ARGV.each { |expression| eval(expression) }
|
||||
|
||||
bm(6) do |x|
|
||||
ARGV.each_with_index do |expression, idx|
|
||||
x.report("##{idx + 1}") { N.times { eval(expression) } }
|
||||
class BenchmarkerTest < ActionDispatch::PerformanceTest
|
||||
self.profile_options = options
|
||||
|
||||
ARGV.each do |expression|
|
||||
eval <<-RUBY
|
||||
def test_#{expression.parameterize('_')}
|
||||
#{expression}
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
@ -1,48 +1,32 @@
|
||||
require 'active_support/core_ext/object/inclusion'
|
||||
require 'optparse'
|
||||
require 'rails/test_help'
|
||||
require 'rails/performance_test_help'
|
||||
require 'active_support/testing/performance'
|
||||
|
||||
if ARGV.first.in?([nil, "-h", "--help"])
|
||||
$stderr.puts "Usage: rails profiler 'Person.expensive_method(10)' [times] [flat|graph|graph_html]"
|
||||
exit(1)
|
||||
end
|
||||
|
||||
# Define a method to profile.
|
||||
if ARGV[1] and ARGV[1].to_i > 1
|
||||
eval "def profile_me() #{ARGV[1]}.times { #{ARGV[0]} } end"
|
||||
else
|
||||
eval "def profile_me() #{ARGV[0]} end"
|
||||
end
|
||||
|
||||
# Use the ruby-prof extension if available. Fall back to stdlib profiler.
|
||||
begin
|
||||
begin
|
||||
require "ruby-prof"
|
||||
$stderr.puts 'Using the ruby-prof extension.'
|
||||
RubyProf.measure_mode = RubyProf::WALL_TIME
|
||||
RubyProf.start
|
||||
profile_me
|
||||
results = RubyProf.stop
|
||||
if ARGV[2]
|
||||
printer_class = RubyProf.const_get((ARGV[2] + "_printer").classify)
|
||||
else
|
||||
printer_class = RubyProf::FlatPrinter
|
||||
end
|
||||
printer = printer_class.new(results)
|
||||
printer.print($stderr)
|
||||
rescue LoadError
|
||||
require "prof"
|
||||
$stderr.puts 'Using the old ruby-prof extension.'
|
||||
Prof.clock_mode = Prof::GETTIMEOFDAY
|
||||
Prof.start
|
||||
profile_me
|
||||
results = Prof.stop
|
||||
require 'rubyprof_ext'
|
||||
Prof.print_profile(results, $stderr)
|
||||
def options
|
||||
options = {}
|
||||
defaults = ActiveSupport::Testing::Performance::DEFAULTS
|
||||
|
||||
OptionParser.new do |opt|
|
||||
opt.banner = "Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]"
|
||||
opt.on('-r', '--runs N', Numeric, 'Number of runs.', "Default: #{defaults[:runs]}") { |r| options[:runs] = r }
|
||||
opt.on('-o', '--output PATH', String, 'Directory to use when writing the results.', "Default: #{defaults[:output]}") { |o| options[:output] = o }
|
||||
opt.on('-m', '--metrics a,b,c', Array, 'Metrics to use.', "Default: #{defaults[:metrics].join(",")}") { |m| options[:metrics] = m.map(&:to_sym) }
|
||||
opt.on('-f', '--formats x,y,z', Array, 'Formats to output to.', "Default: #{defaults[:formats].join(",")}") { |m| options[:formats] = m.map(&:to_sym) }
|
||||
opt.parse!(ARGV)
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
class ProfilerTest < ActionDispatch::PerformanceTest
|
||||
self.profile_options = options
|
||||
|
||||
ARGV.each do |expression|
|
||||
eval <<-RUBY
|
||||
def test_#{expression.parameterize('_')}
|
||||
#{expression}
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
rescue LoadError
|
||||
require 'profiler'
|
||||
$stderr.puts 'Using the standard Ruby profiler.'
|
||||
Profiler__.start_profile
|
||||
profile_me
|
||||
Profiler__.stop_profile
|
||||
Profiler__.print_profile($stderr)
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user