diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2014-10-13 10:55:55 -0300 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2014-10-13 10:55:55 -0300 |
commit | 33361a50eb79fc63125be87508c48b31921b8027 (patch) | |
tree | d087e8245bb6fcbeb86f1f223232e34879ce704a /tools | |
parent | 664a0fa9cf461e7cf3e56c4928eb3c7aa6fe08dd (diff) | |
download | rails-33361a50eb79fc63125be87508c48b31921b8027.tar.gz rails-33361a50eb79fc63125be87508c48b31921b8027.tar.bz2 rails-33361a50eb79fc63125be87508c48b31921b8027.zip |
Revert "Merge pull request #17247 from igas/fix-deprecations"
This reverts commit 997f1575f78bf6a2d12b8665a55807d51fe964df, reversing
changes made to f919d5f5ea75f0e56a57643e5a0472367a98625f.
See https://github.com/rails/rails/pull/17247#issuecomment-58895078
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/profile | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/tools/profile b/tools/profile new file mode 100755 index 0000000000..a35dd18b77 --- /dev/null +++ b/tools/profile @@ -0,0 +1,133 @@ +#!/usr/bin/env ruby +# Example: +# tools/profile activesupport/lib/active_support.rb [ruby-prof mode] [ruby-prof printer] +ENV['NO_RELOAD'] ||= '1' +ENV['RAILS_ENV'] ||= 'development' + +module CodeTools + class Profiler + Error = Class.new(StandardError) + + attr_reader :path, :mode + def initialize(path, mode=nil) + assert_ruby_file_exists(path) + @path, @mode = path, mode + require 'benchmark' + end + + def profile_requires + GC.start + before_rss = `ps -o rss= -p #{Process.pid}`.to_i + + 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 + + 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 + + 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 + + private + + def assert_ruby_file_exists(path) + fail Error.new("No such file") unless File.exists?(path) + fail Error.new("#{path} is a directory") if File.directory?(path) + ruby_extension = File.extname(path) == '.rb' + ruby_executable = File.open(path, 'rb') {|f| f.readline } =~ [/\A#!.*ruby/] + fail Error.new("Not a ruby file") unless ruby_extension or ruby_executable + end + + 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 +# ruby-prof printer name causes the third arg to be sent :classify +# which is probably overkill if you already know the name of the ruby-prof +# printer you want to use, e.g. Graph +begin + require 'active_support/inflector' + require 'active_support/core_ext/string/inflections' +rescue LoadError + STDERR.puts $!.message + class String + # File activesupport/lib/active_support/inflector/methods.rb, line 150 + def classify + # strip out any leading schema name + camelize(self.sub(/.*\./, '')) + end + # File activesupport/lib/active_support/inflector/methods.rb, line 68 + def camelize(uppercase_first_letter = true) + string = self + if uppercase_first_letter + string = string.sub(/^[a-z\d]*/) { $&.capitalize } + else + string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { $&.downcase } + end + string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub('/', '::') + end + end +end +if $0 == __FILE__ + if (filename = ARGV.shift) + path = File.expand_path(filename) + mode = ARGV.shift + CodeTools::Profiler.new(path, mode).profile_requires + else + STDERR.puts "No file path entered. Usage is tools/profile path/to/file.rb [ruby-prof mode] [ruby-prof printer]" + end +end |