Skip to content

Instantly share code, notes, and snippets.

@deepak
Created July 6, 2010 14:17
Show Gist options
  • Save deepak/465431 to your computer and use it in GitHub Desktop.
Save deepak/465431 to your computer and use it in GitHub Desktop.
Gather memory usage per files required and the time taken - useful to reduce startup time
# ACK:
# modified from
# http://gist.github.com/264496 by github.com/eric
# http://gist.github.com/465293 by github.com/alexyoung
# USAGE:
# 1) > ruby -rrequire_tracking -e "require 'active_support'"
# 2) put in config/preinitializer.rb
# WHAT: Provides a simple overview of memory allocation occuring
# during a require.
#
# For a longer explanation, see post at:
# http://bitmonkey.net/post/308322913/tracking-initial-memory-usage-by-file-in-ruby
#
# NOTE: The numbers provided are of self + children, meaning the same will
# be attributed to multiple files at once.
#
# Also, memory that is no longer referenced (and would be freed) is
# still taken into account.
#
# It is intended to give a simple overview of allocations to track
# down gross offenders, not give an exact view of your memory usage.
require 'benchmark'
if GC.respond_to?(:enable_stats)
module RequireTracking
def require(*args)
start_allocated_size = GC.allocated_size
output = nil
benchmark = Benchmark.realtime do #Benchmark.measure
output = super
end
benchmark = (benchmark * 100000).to_i
first_caller = caller[0][40..-1].split(':')[0]
$my_require_stats << [args[0], benchmark, first_caller, (GC.allocated_size - start_allocated_size)]
end #def
end #module
else
module RequireTracking
def require(*args)
output = nil
benchmark = Benchmark.realtime do #Benchmark.measure
output = super
end
benchmark = (benchmark * 1000_00).to_i
first_caller = caller[0][40..-1].split(':')[0]
$my_require_stats << [path, benchmark, first_caller, 'NA']
end #def
end #module
puts "Warning: Not running with an interpreter with GC statistics"
end #if
module RequireTracking
$my_require_stats ||= []
$require_stats_top ||= 20
def numeric_thousands_indicators(number)
number.to_s.gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2')
end
def dump_require_benchmark_stats
File.open('require_trace.log.csv', 'w') do |out|
out << "\"path\",\"benchmark\",\"caller\",\"mem\"\n"
$my_require_stats.each do |path, benchmark, caller, mem|
out << "\"#{path}\",\"#{benchmark}\",\"#{caller}\",\"#{mem}\"\n"
end
end
end
def print_require_benchmark_stats_by_memory
puts " %40s %5s %5s " % [ 'File', 'KB', 'NanoSec' ]
puts " %40s %s" % [ '-------------', '--------' ]
$my_require_stats.sort_by {|v| v[3] }.slice(0, $require_stats_top).each do |path, benchmark, caller, mem|
puts "%40s %5s %5s " % [ path, numeric_thousands_indicators(mem / 1024), benchmark ]
end
end
def print_require_benchmark_stats_by_time
puts " %40s %5s %5s " % [ 'File', 'KB', 'NanoSec' ]
puts " %40s %s" % [ '-------------', '--------' ]
$my_require_stats.sort_by {|v| v[1] }.slice(0, $require_stats_top).each do |path, benchmark, caller, mem|
puts "%40s %5s %5s " % [ path, numeric_thousands_indicators(mem / 1024), benchmark ]
end
end
end #module
Object.send(:include, RequireTracking)
Kernel.send(:include, RequireTracking)
if GC.respond_to?(:enable_stats)
GC.enable_stats
GC.clear_stats
end
at_exit do
dump_require_benchmark_stats
puts "Memory used by file:"
print_require_benchmark_stats_by_memory
puts "Time required by file:"
print_require_benchmark_stats_by_time
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment