X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=vendor%2Frails%2Factionpack%2Flib%2Faction_controller%2Frequest_profiler.rb;fp=vendor%2Frails%2Factionpack%2Flib%2Faction_controller%2Frequest_profiler.rb;h=a6471d0c08a131c22e6ae2cf58a58b9eae57aff9;hb=d115f2e23823271635bad69229a42cd8ac68debe;hp=0000000000000000000000000000000000000000;hpb=37cb670bf3ddde90b214e591f100ed4446469484;p=depot.git diff --git a/vendor/rails/actionpack/lib/action_controller/request_profiler.rb b/vendor/rails/actionpack/lib/action_controller/request_profiler.rb new file mode 100644 index 0000000..a6471d0 --- /dev/null +++ b/vendor/rails/actionpack/lib/action_controller/request_profiler.rb @@ -0,0 +1,169 @@ +require 'optparse' +require 'action_controller/integration' + +module ActionController + class RequestProfiler + # Wrap up the integration session runner. + class Sandbox + include Integration::Runner + + def self.benchmark(n, script) + new(script).benchmark(n) + end + + def initialize(script_path) + @quiet = false + define_run_method(script_path) + reset! + end + + def benchmark(n, profiling = false) + @quiet = true + print ' ' + + result = Benchmark.realtime do + n.times do |i| + run(profiling) + print_progress(i) + end + end + + puts + result + ensure + @quiet = false + end + + def say(message) + puts " #{message}" unless @quiet + end + + private + def define_run_method(script_path) + script = File.read(script_path) + + source = <<-end_source + def run(profiling = false) + if profiling + RubyProf.resume do + #{script} + end + else + #{script} + end + + old_request_count = request_count + reset! + self.request_count = old_request_count + end + end_source + + instance_eval source, script_path, 1 + end + + def print_progress(i) + print "\n " if i % 60 == 0 + print ' ' if i % 10 == 0 + print '.' + $stdout.flush + end + end + + + attr_reader :options + + def initialize(options = {}) + @options = default_options.merge(options) + end + + + def self.run(args = nil, options = {}) + profiler = new(options) + profiler.parse_options(args) if args + profiler.run + end + + def run + sandbox = Sandbox.new(options[:script]) + + puts 'Warming up once' + + elapsed = warmup(sandbox) + puts '%.2f sec, %d requests, %d req/sec' % [elapsed, sandbox.request_count, sandbox.request_count / elapsed] + puts "\n#{options[:benchmark] ? 'Benchmarking' : 'Profiling'} #{options[:n]}x" + + options[:benchmark] ? benchmark(sandbox) : profile(sandbox) + end + + def profile(sandbox) + load_ruby_prof + + benchmark(sandbox, true) + results = RubyProf.stop + + show_profile_results results + results + end + + def benchmark(sandbox, profiling = false) + sandbox.request_count = 0 + elapsed = sandbox.benchmark(options[:n], profiling).to_f + count = sandbox.request_count.to_i + puts '%.2f sec, %d requests, %d req/sec' % [elapsed, count, count / elapsed] + end + + def warmup(sandbox) + Benchmark.realtime { sandbox.run(false) } + end + + def default_options + { :n => 100, :open => 'open %s &' } + end + + # Parse command-line options + def parse_options(args) + OptionParser.new do |opt| + opt.banner = "USAGE: #{$0} [options] [session script path]" + + opt.on('-n', '--times [100]', 'How many requests to process. Defaults to 100.') { |v| options[:n] = v.to_i if v } + opt.on('-b', '--benchmark', 'Benchmark instead of profiling') { |v| options[:benchmark] = v } + opt.on('-m', '--measure [mode]', 'Which ruby-prof measure mode to use: process_time, wall_time, cpu_time, allocations, or memory. Defaults to process_time.') { |v| options[:measure] = v } + opt.on('--open [CMD]', 'Command to open profile results. Defaults to "open %s &"') { |v| options[:open] = v } + opt.on('-h', '--help', 'Show this help') { puts opt; exit } + + opt.parse args + + if args.empty? + puts opt + exit + end + options[:script] = args.pop + end + end + + protected + def load_ruby_prof + begin + gem 'ruby-prof', '>= 0.6.1' + require 'ruby-prof' + if mode = options[:measure] + RubyProf.measure_mode = RubyProf.const_get(mode.upcase) + end + rescue LoadError + abort '`gem install ruby-prof` to use the profiler' + end + end + + def show_profile_results(results) + File.open "#{RAILS_ROOT}/tmp/profile-graph.html", 'w' do |file| + RubyProf::GraphHtmlPrinter.new(results).print(file) + `#{options[:open] % file.path}` if options[:open] + end + + File.open "#{RAILS_ROOT}/tmp/profile-flat.txt", 'w' do |file| + RubyProf::FlatPrinter.new(results).print(file) + `#{options[:open] % file.path}` if options[:open] + end + end + end +end