Froze rails gems
[depot.git] / vendor / rails / actionpack / lib / action_controller / request_profiler.rb
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, profiling = false)
21 @quiet = true
22 print ' '
23
24 result = Benchmark.realtime do
25 n.times do |i|
26 run(profiling)
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(profiling = false)
47 if profiling
48 RubyProf.resume do
49 #{script}
50 end
51 else
52 #{script}
53 end
54
55 old_request_count = request_count
56 reset!
57 self.request_count = old_request_count
58 end
59 end_source
60
61 instance_eval source, script_path, 1
62 end
63
64 def print_progress(i)
65 print "\n " if i % 60 == 0
66 print ' ' if i % 10 == 0
67 print '.'
68 $stdout.flush
69 end
70 end
71
72
73 attr_reader :options
74
75 def initialize(options = {})
76 @options = default_options.merge(options)
77 end
78
79
80 def self.run(args = nil, options = {})
81 profiler = new(options)
82 profiler.parse_options(args) if args
83 profiler.run
84 end
85
86 def run
87 sandbox = Sandbox.new(options[:script])
88
89 puts 'Warming up once'
90
91 elapsed = warmup(sandbox)
92 puts '%.2f sec, %d requests, %d req/sec' % [elapsed, sandbox.request_count, sandbox.request_count / elapsed]
93 puts "\n#{options[:benchmark] ? 'Benchmarking' : 'Profiling'} #{options[:n]}x"
94
95 options[:benchmark] ? benchmark(sandbox) : profile(sandbox)
96 end
97
98 def profile(sandbox)
99 load_ruby_prof
100
101 benchmark(sandbox, true)
102 results = RubyProf.stop
103
104 show_profile_results results
105 results
106 end
107
108 def benchmark(sandbox, profiling = false)
109 sandbox.request_count = 0
110 elapsed = sandbox.benchmark(options[:n], profiling).to_f
111 count = sandbox.request_count.to_i
112 puts '%.2f sec, %d requests, %d req/sec' % [elapsed, count, count / elapsed]
113 end
114
115 def warmup(sandbox)
116 Benchmark.realtime { sandbox.run(false) }
117 end
118
119 def default_options
120 { :n => 100, :open => 'open %s &' }
121 end
122
123 # Parse command-line options
124 def parse_options(args)
125 OptionParser.new do |opt|
126 opt.banner = "USAGE: #{$0} [options] [session script path]"
127
128 opt.on('-n', '--times [100]', 'How many requests to process. Defaults to 100.') { |v| options[:n] = v.to_i if v }
129 opt.on('-b', '--benchmark', 'Benchmark instead of profiling') { |v| options[:benchmark] = v }
130 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 }
131 opt.on('--open [CMD]', 'Command to open profile results. Defaults to "open %s &"') { |v| options[:open] = v }
132 opt.on('-h', '--help', 'Show this help') { puts opt; exit }
133
134 opt.parse args
135
136 if args.empty?
137 puts opt
138 exit
139 end
140 options[:script] = args.pop
141 end
142 end
143
144 protected
145 def load_ruby_prof
146 begin
147 gem 'ruby-prof', '>= 0.6.1'
148 require 'ruby-prof'
149 if mode = options[:measure]
150 RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
151 end
152 rescue LoadError
153 abort '`gem install ruby-prof` to use the profiler'
154 end
155 end
156
157 def show_profile_results(results)
158 File.open "#{RAILS_ROOT}/tmp/profile-graph.html", 'w' do |file|
159 RubyProf::GraphHtmlPrinter.new(results).print(file)
160 `#{options[:open] % file.path}` if options[:open]
161 end
162
163 File.open "#{RAILS_ROOT}/tmp/profile-flat.txt", 'w' do |file|
164 RubyProf::FlatPrinter.new(results).print(file)
165 `#{options[:open] % file.path}` if options[:open]
166 end
167 end
168 end
169 end