Skip to content

Instantly share code, notes, and snippets.

@thinkerbot
Created August 16, 2008 17:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thinkerbot/5732 to your computer and use it in GitHub Desktop.
Save thinkerbot/5732 to your computer and use it in GitHub Desktop.
A load time profiler script
# = Description
# A load time profiler script, useful for identifying requires
# that slow down the loading of a script.
#
# Oftentimes we use but don't always need what we require in
# scripts. This can dramatically slow load times, which can be
# annoying. Use this script to identify slow-loading parts of
# a script and then consider using autoloading to defer
# the require until you really need it.
#
# #require 'stringio'
# autoload(:StringIO, 'stringio')
#
# = Usage
#
# Simply cut-n-paste this script before your first require
# statements (or add the requires at the end of this script):
#
# [profile_load_time.rb ]
# # ... this script ...
#
# require 'time'
#
# Then from the command line:
#
# % ruby profile_load_time.rb
# ================================================================================
# Require/Load Profile (time in ms)
# * Load times > 0.5 ms
# - duplicate requires
# ================================================================================
# * 9.1: time
# * 5.2: parsedate
# * 5.0: date/format
# * 1.2: rational
#
# Total time: 9.105 ms
#
# = Info
# Developer:: Simon Chiang (http://bahuvrihi.wordpress.com)
# Licence:: MIT-Style (http://en.wikipedia.org/wiki/MIT_License)
# Gist:: http://gist.github.com/5732
class RecursiveProfile
class << self
def instance
@@instance
end
def [](key)
@@variables[key]
end
def []=(key, value)
@@variables[key] = value
end
end
attr_reader :results
def initialize
@results = []
end
def profile
current = @results
@results = []
start = Time.now
target = [yield]
target << Time.now-start
target << @results
@results = current
@results << target
end
def each
recurse(@results, 0) do |value, time, nesting_depth|
yield(value, time, nesting_depth)
end
end
private
def recurse(parent, nesting_depth, &block)
parent.each do |value, time, children|
yield(value, time, nesting_depth)
recurse(children, nesting_depth + 1, &block)
end
end
@@instance = RecursiveProfile.new
@@variables = {}
end
def require(path)
RecursiveProfile.instance.profile do
begin
super
path
rescue(Exception)
"#{path} (error: #{$!.message})"
end
end
end
def load(path)
RecursiveProfile.instance.profile do
begin
super
path
rescue(Exception)
"#{path} (error: #{$!.message})"
end
end
end
at_exit do
total_time = (Time.now - RecursiveProfile[:start]) * 10**3
values = []
duplicates = []
RecursiveProfile.instance.each do |value, time, nesting_depth|
(values.include?(value) ? duplicates : values) << value
end
puts "=" * 80
puts "Require/Load Profile (time in ms)"
puts "* Load time > #{RecursiveProfile[:cutoff_in_ms]} ms"
puts "- Duplicate require"
puts "=" * 80
RecursiveProfile.instance.each do |value, time, nesting_depth|
time_in_ms = time * 10**3
flags = (time_in_ms > RecursiveProfile[:cutoff_in_ms] ? '*' : ' ')
flags = "-" if duplicates.include?(value) && !values.include?(value)
values.delete(value)
puts "#{flags} #{' ' * nesting_depth}#{"%.1f" % time_in_ms}: #{value}"
end
puts
puts "Total time: #{total_time} ms"
end
RecursiveProfile[:cutoff_in_ms] = 0.5
RecursiveProfile[:start] = Time.now
###############################################################################
# add requires here
###############################################################################
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment