aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorBenjamin Fleischer <github@benjaminfleischer.com>2014-07-25 12:09:49 -0500
committerBenjamin Fleischer <github@benjaminfleischer.com>2014-07-25 13:41:18 -0500
commitf36c46754fa420343e7b01695f09e62293a40597 (patch)
treebf08746412ec38954da20fd3300188563545dc30 /tools
parent65a227beda8c32972cb6fdb17ca93a4f5e828044 (diff)
downloadrails-f36c46754fa420343e7b01695f09e62293a40597.tar.gz
rails-f36c46754fa420343e7b01695f09e62293a40597.tar.bz2
rails-f36c46754fa420343e7b01695f09e62293a40597.zip
Encapsulate tools/profile functionality in CodeTools::Profiler
Fix bug in path expansion of input filepath [ci skip]
Diffstat (limited to 'tools')
-rwxr-xr-xtools/profile128
1 files changed, 76 insertions, 52 deletions
diff --git a/tools/profile b/tools/profile
index d4b2fc5fbd..5c916aafc8 100755
--- a/tools/profile
+++ b/tools/profile
@@ -1,71 +1,95 @@
#!/usr/bin/env ruby
# Example:
-# ./profile ../activesupport/lib/active_support.rb [ruby-prof mode]
+# tools/profile activesupport/lib/active_support.rb [ruby-prof mode] [ruby-prof printer]
ENV['NO_RELOAD'] ||= '1'
ENV['RAILS_ENV'] ||= 'development'
-require 'benchmark'
+module CodeTools
+ class Profiler
-module RequireProfiler
- private
- def require(file, *args) RequireProfiler.profile(file) { super } end
- def load(file, *args) RequireProfiler.profile(file) { super } end
-
- @depth, @stats = 0, []
- class << self
- attr_accessor :depth
- attr_accessor :stats
-
- def profile(file)
- stats << [file, depth]
- self.depth += 1
- result = nil
- elapsed = Benchmark.realtime { result = yield }
- self.depth -= 1
- stats.pop if stats.last.first == file
- stats << [file, depth, elapsed] if result
- result
+ attr_reader :path, :mode
+ def initialize(path, mode=nil)
+ @path, @mode = path, mode
+ require 'benchmark'
end
- end
-end
-GC.start
-before_rss = `ps -o rss= -p #{Process.pid}`.to_i
+ def profile_requires
+ GC.start
+ before_rss = `ps -o rss= -p #{Process.pid}`.to_i
-path = ARGV.shift
-if mode = ARGV.shift
- require 'ruby-prof'
- RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
- RubyProf.start
-else
- Object.instance_eval { include RequireProfiler }
-end
+ if mode
+ require 'ruby-prof'
+ RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
+ RubyProf.start
+ else
+ Object.instance_eval { include RequireProfiler }
+ end
+
+ elapsed = Benchmark.realtime { require path }
+ results = RubyProf.stop if mode
-elapsed = Benchmark.realtime { require path }
-results = RubyProf.stop if mode
+ GC.start
+ after_rss = `ps -o rss= -p #{Process.pid}`.to_i
-GC.start
-after_rss = `ps -o rss= -p #{Process.pid}`.to_i
+ if mode
+ if printer = ARGV.shift
+ puts "RubyProf outputting to stderr with printer #{printer}"
+ RubyProf.const_get("#{printer.to_s.classify}Printer").new(results).print($stdout)
+ elsif RubyProf.const_defined?(:CallStackPrinter)
+ filename = "#{File.basename(path, '.rb')}.#{mode}.html"
+ puts "RubyProf outputting to #{filename}"
+ File.open(filename, 'w') do |out|
+ RubyProf::CallStackPrinter.new(results).print(out)
+ end
+ else
+ filename = "#{File.basename(path, '.rb')}.#{mode}.callgrind"
+ puts "RubyProf outputting to #{filename}"
+ File.open(filename, 'w') do |out|
+ RubyProf::CallTreePrinter.new(results).print(out)
+ end
+ end
+ end
-if mode
- if printer = ARGV.shift
- RubyProf.const_get("#{printer.to_s.classify}Printer").new(results).print($stdout)
- elsif RubyProf.const_defined?(:CallStackPrinter)
- File.open("#{File.basename(path, '.rb')}.#{mode}.html", 'w') do |out|
- RubyProf::CallStackPrinter.new(results).print(out)
+ RequireProfiler.stats.each do |file, depth, sec|
+ if sec
+ puts "%8.1f ms %s%s" % [sec * 1000, ' ' * depth, file]
+ else
+ puts "#{' ' * (13 + depth)}#{file}"
+ end
+ end
+ puts "%8.1f ms %d KB RSS" % [elapsed * 1000, after_rss - before_rss]
end
- else
- File.open("#{File.basename(path, '.rb')}.#{mode}.callgrind", 'w') do |out|
- RubyProf::CallTreePrinter.new(results).print(out)
+
+ module RequireProfiler
+ private
+ def require(file, *args) RequireProfiler.profile(file) { super } end
+ def load(file, *args) RequireProfiler.profile(file) { super } end
+
+ @depth, @stats = 0, []
+ class << self
+ attr_accessor :depth
+ attr_accessor :stats
+
+ def profile(file)
+ stats << [file, depth]
+ self.depth += 1
+ result = nil
+ elapsed = Benchmark.realtime { result = yield }
+ self.depth -= 1
+ stats.pop if stats.last.first == file
+ stats << [file, depth, elapsed] if result
+ result
+ end
+ end
end
end
end
-
-RequireProfiler.stats.each do |file, depth, sec|
- if sec
- puts "%8.1f ms %s%s" % [sec * 1000, ' ' * depth, file]
+if $0 == __FILE__
+ if (filename = ARGV.shift)
+ path = File.expand_path(filename)
+ mode = ARGV.shift
+ CodeTools::Profiler.new(path, mode).profile_requires
else
- puts "#{' ' * (13 + depth)}#{file}"
+ STDERR.puts "No file path entered. Usage is tools/profile path/to/file.rb [ruby-prof mode] [ruby-prof printer]"
end
end
-puts "%8.1f ms %d KB RSS" % [elapsed * 1000, after_rss - before_rss]