A Rails action processor that profiles an entire action.
ProfiledProcessor is an abstract class. A subclasses must implement start_profile, stop_profile and print_profile.
- load_default_processor
- load_processor
- new
- print_profile
- process_args
- profile
- start_profile
- stop_profile
| PROFILERS | = | ['ZenProfiler', 'Prof', 'Profiler'] |
Attempts to load the default profilers in order. Returns the first successfully found profiler class.
[ show source ]
# File lib/action_profiler/profiled_processor.rb, line 128
128: def self.load_default_processor
129: PROFILERS.each do |profiler|
130: begin
131: return load_processor(profiler)
132: rescue LoadError => e
133: end
134: end
135: raise "couldn't load any profilers, how strange, sorry about that"
136: end
Attempts to load a processor starting with name. Returns the loaded class if successful.
[ show source ]
# File lib/action_profiler/profiled_processor.rb, line 142
142: def self.load_processor(name)
143: debug "Loading #{name}Processor"
144: # HACK I have no fucking clue how or why Rails' require mucks shit up,
145: # nor can I reproduce it in a small testcase.
146: require__ "action_profiler/#{name.downcase}_processor"
147: return Object.path2class("#{name}Processor")
148: rescue LoadError => e
149: debug "Failed to load #{name}Processor: #{e.message}"
150: raise
151: end
If only_html is true then only the rendered page will be displayed and no profiling will be performed. See TestProcessor#new for the rest.
[ show source ]
# File lib/action_profiler/profiled_processor.rb, line 157
157: def initialize(action, method, params, session, flash, only_html)
158: super action, method, params, session, flash
159: @only_html = only_html
160: end
Processes args then runs a profile based on the arguments given.
[ show source ]
# File lib/action_profiler/profiled_processor.rb, line 22
22: def self.process_args(args = ARGV)
23: app_path = Dir.pwd
24: method = 'GET'
25: only_html = false
26: processor_klass = nil
27: times = 1
28:
29: opts = OptionParser.new do |opts|
30: opts.banner = "Usage: #{File.basename $0} [options] method [params [session [flash]]]"
31:
32: opts.separator ''
33: opts.separator 'method: controller and action to run "GamesController#index"'
34: opts.separator 'params, session, flash: Hash-style arguments ":id => 5"'
35: opts.separator ''
36:
37: opts.on("-m", "--method=HTTP_METHOD",
38: "HTTP request method for this action",
39: "Default: #{method}") do |val|
40: method = val
41: end
42:
43: opts.on("-o", "--[no-]only-html",
44: "Only output rendered page",
45: "Default: #{only_html}") do |val|
46: only_html = val
47: end
48:
49: opts.on("-p", "--app-path=PATH",
50: "Path to Rails application root",
51: "Default: current directory") do |val|
52: unless File.directory? val then
53: raise OptionParser::InvalidArgument, "bad path: #{val}"
54: end
55:
56: app_path = val
57: end
58:
59: opts.on("-P", "--profiler=PROFILER",
60: "Profiler to use",
61: "Default: ZenProfiler, Prof then Profiler") do |val|
62: begin
63: processor_klass = load_processor val
64: rescue LoadError
65: raise OptionParser::InvalidArgument, "can't load #{val}_processor"
66: end
67: end
68:
69: opts.on("-t", "--times=TIMES", Integer,
70: "Times to run the action under the profiler",
71: "Default: #{times}") do |val|
72: times = val
73: end
74:
75: opts.separator ''
76: opts.on("-h", "--help", "Display this help") { STDERR.puts opts; exit 1 }
77: opts.on("-d", "--debug", "Enable debugging output") do |val|
78: $AP_DEBUG = val
79: end
80: opts.separator ''
81:
82: opts.parse! args
83: end
84:
85: processor_klass = load_default_processor if processor_klass.nil?
86:
87: begin
88: Dir.chdir app_path
89: require 'config/environment'
90: require 'application' # HACK Rails can't find this by itself
91: rescue LoadError => e
92: debug "Application load error \"#{e.message}\""
93: raise OptionParser::InvalidArgument, "could not load application, check your path"
94: end
95:
96: raise OptionParser::ParseError, "action not specified" if args.empty?
97: action = args.shift
98:
99: raise OptionParser::ParseError, "too many arguments" if args.length > 3
100:
101: begin
102: params, session, flash = args.map { |arg| eval "{#{arg}}" }
103: rescue Exception
104: raise OptionParser::ParseError, "invalid param/session/flash argument"
105: end
106:
107: params ||= {}
108: session ||= {}
109: flash ||= {}
110:
111: debug "Using #{processor_klass.inspect} processor"
112:
113: pp = processor_klass.new action, method, params, session, flash, only_html
114: pp.profile times
115:
116: rescue ArgumentError, OptionParser::ParseError => e
117: STDERR.puts e.message
118: debug "\t#{$!.backtrace.join("\n\t")}"
119: STDERR.puts
120: STDERR.puts opts.to_s
121: exit 1
122: end
Implemented by a subclass to print out the profile data to io.
[ show source ]
# File lib/action_profiler/profiled_processor.rb, line 203
203: def print_profile(io)
204: raise NotImplementedError
205: end
Profiles the action, running it under the profiler times times after three warmup actions.
[ show source ]
# File lib/action_profiler/profiled_processor.rb, line 166
166: def profile(times = 1)
167: if @only_html then
168: process
169: puts @response.body
170: return
171: end
172:
173: STDERR.puts "Warmup..."
174: 3.times { process }
175:
176: begin
177: STDERR.puts "Profiling..."
178: start_profile
179: times.times { process }
180: stop_profile
181: ensure
182: print_profile
183: end
184: end
Implemented by a subclass to start the profiler it uses.
[ show source ]
# File lib/action_profiler/profiled_processor.rb, line 189
189: def start_profile
190: raise NotImplementedError
191: end
Implemented by a subclass to stop the profiler it uses.
[ show source ]
# File lib/action_profiler/profiled_processor.rb, line 196
196: def stop_profile
197: raise NotImplementedError
198: end