Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/trunk/actionpack/lib/action_controller/request_profiler.rb

Revision 8792, 4.1 kB (checked in by bitsweat, 7 months ago)

Add --measure option to script/performance/request to set ruby-prof measure mode: process_time, wall_time, cpu_time, allocations, memory.

  • Property svn:executable set to *
Line 
1 require 'optparse'
2 require 'action_controller/integration'
3
4 module ActionController
5   class RequestProfiler
6     # Wrap up the integration session runner.
7     class Sandbox
8       include Integration::Runner
9
10       def self.benchmark(n, script)
11         new(script).benchmark(n)
12       end
13
14       def initialize(script_path)
15         @quiet = false
16         define_run_method(script_path)
17         reset!
18       end
19
20       def benchmark(n)
21         @quiet = true
22         print '  '
23
24         result = Benchmark.realtime do
25           n.times do |i|
26             run
27             print_progress(i)
28           end
29         end
30
31         puts
32         result
33       ensure
34         @quiet = false
35       end
36
37       def say(message)
38         puts "  #{message}" unless @quiet
39       end
40
41       private
42         def define_run_method(script_path)
43           script = File.read(script_path)
44
45           source = <<-end_source
46             def run
47               #{script}
48               old_request_count = request_count
49               reset!
50               self.request_count = old_request_count
51             end
52           end_source
53
54           instance_eval source, script_path, 1
55         end
56
57         def print_progress(i)
58           print "\n  " if i % 60 == 0
59           print ' ' if i % 10 == 0
60           print '.'
61           $stdout.flush
62         end
63     end
64
65
66     attr_reader :options
67
68     def initialize(options = {})
69       @options = default_options.merge(options)
70     end
71
72
73     def self.run(args = nil, options = {})
74       profiler = new(options)
75       profiler.parse_options(args) if args
76       profiler.run
77     end
78
79     def run
80       sandbox = Sandbox.new(options[:script])
81
82       puts 'Warming up once'
83
84       elapsed = warmup(sandbox)
85       puts '%.2f sec, %d requests, %d req/sec' % [elapsed, sandbox.request_count, sandbox.request_count / elapsed]
86       puts "\n#{options[:benchmark] ? 'Benchmarking' : 'Profiling'} #{options[:n]}x"
87
88       options[:benchmark] ? benchmark(sandbox) : profile(sandbox)
89     end
90
91     def profile(sandbox)
92       load_ruby_prof
93
94       results = RubyProf.profile { benchmark(sandbox) }
95
96       show_profile_results results
97       results
98     end
99
100     def benchmark(sandbox)
101       sandbox.request_count = 0
102       elapsed = sandbox.benchmark(options[:n]).to_f
103       count = sandbox.request_count.to_i
104       puts '%.2f sec, %d requests, %d req/sec' % [elapsed, count, count / elapsed]
105     end
106
107     def warmup(sandbox)
108       Benchmark.realtime { sandbox.run }
109     end
110
111     def default_options
112       { :n => 100, :open => 'open %s &' }
113     end
114
115     # Parse command-line options
116     def parse_options(args)
117       OptionParser.new do |opt|
118         opt.banner = "USAGE: #{$0} [options] [session script path]"
119
120         opt.on('-n', '--times [100]', 'How many requests to process. Defaults to 100.') { |v| options[:n] = v.to_i if v }
121         opt.on('-b', '--benchmark', 'Benchmark instead of profiling') { |v| options[:benchmark] = v }
122         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 }
123         opt.on('--open [CMD]', 'Command to open profile results. Defaults to "open %s &"') { |v| options[:open] = v }
124         opt.on('-h', '--help', 'Show this help') { puts opt; exit }
125
126         opt.parse args
127
128         if args.empty?
129           puts opt
130           exit
131         end
132         options[:script] = args.pop
133       end
134     end
135
136     protected
137       def load_ruby_prof
138         begin
139           require 'ruby-prof'
140           if mode = options[:measure]
141             RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
142           end
143         rescue LoadError
144           abort '`gem install ruby-prof` to use the profiler'
145         end
146       end
147
148       def show_profile_results(results)
149         File.open "#{RAILS_ROOT}/tmp/profile-graph.html", 'w' do |file|
150           RubyProf::GraphHtmlPrinter.new(results).print(file)
151           `#{options[:open] % file.path}` if options[:open]
152         end
153
154         File.open "#{RAILS_ROOT}/tmp/profile-flat.txt", 'w' do |file|
155           RubyProf::FlatPrinter.new(results).print(file)
156           `#{options[:open] % file.path}` if options[:open]
157         end
158       end
159   end
160 end
Note: See TracBrowser for help on using the browser.