Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 87 lines (75 sloc) 2.8 kB
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
1 #!/usr/bin/env ruby
2 # Example:
4f291fa @jeremy Simple examples for require profiling
jeremy authored
3 # tools/profile_requires activesupport/lib/active_support.rb
4 # tools/profile_requires activeresource/examples/simple.rb
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
5 abort 'Use REE so you can profile memory and object allocation' unless GC.respond_to?(:enable_stats)
6
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
7 ENV['NO_RELOAD'] ||= '1'
8 ENV['RAILS_ENV'] ||= 'development'
9
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
10 GC.enable_stats
11 require 'rubygems'
12 Gem.source_index
13 require 'benchmark'
14
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
15 module RequireProfiler
577034d @jeremy Ensure require and load are private - h/t apeiros
jeremy authored
16 private
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
17 def require(file, *args) RequireProfiler.profile(file) { super } end
18 def load(file, *args) RequireProfiler.profile(file) { super } end
19
20 @depth, @stats = 0, []
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
21 class << self
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
22 attr_accessor :depth
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
23 attr_accessor :stats
24
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
25 def profile(file)
26 stats << [file, depth]
27 self.depth += 1
28 heap_before, objects_before = GC.allocated_size, ObjectSpace.allocated_objects
29 result = nil
30 elapsed = Benchmark.realtime { result = yield }
31 heap_after, objects_after = GC.allocated_size, ObjectSpace.allocated_objects
32 self.depth -= 1
33 stats.pop if stats.last.first == file
34 stats << [file, depth, elapsed, heap_after - heap_before, objects_after - objects_before] if result
35 result
36 end
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
37 end
38 end
39
40 GC.start
41 before = GC.allocated_size
7b730a2 @jeremy Show GC time and # of runs too
jeremy authored
42 before_gctime, before_gcruns = GC.time, GC.collections
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
43 before_rss = `ps -o rss= -p #{Process.pid}`.to_i
44 before_live_objects = ObjectSpace.live_objects
45
46 path = ARGV.shift
47 if mode = ARGV.shift
48 require 'ruby-prof'
49 RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
50 RubyProf.start
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
51 else
52 Object.instance_eval { include RequireProfiler }
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
53 end
54
55 elapsed = Benchmark.realtime { require path }
56 results = RubyProf.stop if mode
57
7b730a2 @jeremy Show GC time and # of runs too
jeremy authored
58 after_gctime, after_gcruns = GC.time, GC.collections
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
59 GC.start
60 after_live_objects = ObjectSpace.live_objects
61 after_rss = `ps -o rss= -p #{Process.pid}`.to_i
62 after = GC.allocated_size
63 usage = (after - before) / 1024.0
64
65 if mode
4883082 @jeremy Support an extra profile printer arg
jeremy authored
66 if printer = ARGV.shift
67 RubyProf.const_get("#{printer.to_s.classify}Printer").new(results).print($stdout)
68 elsif RubyProf.const_defined?(:CallStackPrinter)
50cdb65 @jeremy Use call stack printer if available
jeremy authored
69 File.open("#{File.basename(path, '.rb')}.#{mode}.html", 'w') do |out|
70 RubyProf::CallStackPrinter.new(results).print(out)
71 end
72 else
73 File.open("#{File.basename(path, '.rb')}.#{mode}.callgrind", 'w') do |out|
74 RubyProf::CallTreePrinter.new(results).print(out)
75 end
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
76 end
77 end
78
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
79 RequireProfiler.stats.each do |file, depth, sec, bytes, objects|
e9c5750 @jeremy Preserve ordering
jeremy authored
80 if sec
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
81 puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * depth, file]
e9c5750 @jeremy Preserve ordering
jeremy authored
82 else
886eeed @jeremy Clean up tools/profile_requires a bit
jeremy authored
83 puts "#{' ' * (42 + depth)}#{file}"
e9c5750 @jeremy Preserve ordering
jeremy authored
84 end
8ee0c59 @jeremy Tool for profiling resource usage in each require call.
jeremy authored
85 end
7b730a2 @jeremy Show GC time and # of runs too
jeremy authored
86 puts "%10.2f KB %10d obj %8.1f ms %d KB RSS %8.1f ms GC time %d GC runs" % [usage, after_live_objects - before_live_objects, elapsed * 1000, after_rss - before_rss, (after_gctime - before_gctime) / 1000.0, after_gcruns - before_gcruns]
Something went wrong with that request. Please try again.