Skip to content

Instantly share code, notes, and snippets.

@lambda2
Forked from jherdman/README.md
Created January 27, 2016 15:30
Show Gist options
  • Select an option

  • Save lambda2/b9a4d292e004c52411c6 to your computer and use it in GitHub Desktop.

Select an option

Save lambda2/b9a4d292e004c52411c6 to your computer and use it in GitHub Desktop.
A Gem loading benchmark script

Benchmark.rb

Because loading gems take longer than you think

$ curl -fsSL https://gist.github.com/raw/5022636/benchmark.rb | ruby
............................................................[DONE]

Gem                            Time(sec)     Pct %
--------------------------------------------------
jazz_hands                        1.1986     12.6%
mongoid                           1.0774     11.4%
fog                               0.7371      7.8%
newrelic_rpm                      0.6181      6.5%
ruby-prof                         0.5841      6.2%
debugger                          0.3582      3.8%
geocoder                          0.3345      3.5%
delayed_job                       0.3147      3.3%
bitly                             0.2678      2.8%
turbo-sprockets-rails3            0.2658      2.8%
sass                              0.2614      2.8%
--------------------------------------------------
Total                             4.8583    100.0%

Forked from this awesome gist by Pan Thomakos.

Use it

curl -fsSL https://gist.github.com/raw/5022636/benchmark.rb | ruby

To only require certains groups (like Rails does), do

# Rails development default groups
curl -fsSL https://gist.github.com/raw/5022636/benchmark.rb | BUNDLE_GROUPS=default,development,assets ruby

Now what?

Read this article

http://iain.nl/getting-the-most-out-of-bundler-groups

The results

I reduced our gem load time from 12.1 seconds to 6.7 seconds - over 5 seconds!

Here's what I did:

  1. Added :console group like the article above suggested

  2. Commented out ruby-prof, oink, and debugger when not in use

  3. Moved newrelic_rpm and turbo-sprockets-rails3 to :staging, :production groups

  4. Removed unused gems

Bonus

time script/rails console # or server, etc

is faster than

time bundle exec rails console

Try it yourself

#!/usr/bin/env ruby
require 'bundler/setup'
require 'benchmark'
REGEXPS = [
/^no such file to load -- (.+)$/i,
/^Missing \w+ (?:file\s*)?([^\s]+.rb)$/i,
/^Missing API definition file in (.+)$/i,
/^cannot load such file -- (.+)$/i
]
groups = ENV["BUNDLE_GROUPS"].to_s.split(",")
groups.map! { |g| g.to_sym }
groups = [:default] if groups.empty?
# taken from https://github.com/carlhuda/bundler/blob/v1.2.4/lib/bundler/runtime.rb
def pull(dep)
required_file = nil
begin
# Loop through all the specified autorequires for the
# dependency. If there are none, use the dependency's name
# as the autorequire.
Array(dep.autorequire || dep.name).each do |file|
required_file = file
Kernel.require file
end
rescue LoadError => e
if dep.autorequire.nil? && dep.name.include?('-')
begin
namespaced_file = dep.name.gsub('-', '/')
Kernel.require namespaced_file
rescue LoadError
REGEXPS.find { |r| r =~ e.message }
regex_name = $1
raise if dep.autorequire || (regex_name && regex_name.gsub('-', '/') != namespaced_file)
raise e if regex_name.nil?
end
else
REGEXPS.find { |r| r =~ e.message }
raise if dep.autorequire || $1 != required_file
end
end
end
dependencies = Bundler.setup.dependencies.map(&:name)
rails_included = dependencies.include?("rails")
if rails_included
rails_time =
Benchmark.realtime do
require 'rails/all'
# If you would prefer gems to incur the cost of autoloading
# Rails frameworks, then comment out this next line.
ActiveSupport::Autoload.eager_autoload!
end
end
$VERBOSE = nil
gems = {}
Bundler.setup.dependencies.each do |dep|
if ((dep.groups & groups).any? && dep.current_platform?)
gems[dep.name] = Benchmark.realtime{ pull(dep) }
putc "."
end
end
puts "[DONE]\n\n"
if rails_included
gems["rails"] = rails_time
end
total = gems.map{|gem, time| time }.inject(0.0){|x, sum| sum + x }
format = "%-30s %9.4f %8.1f%%"
puts "%s %36s %9s" % ["Gem", "Time(sec)", "Pct %"]
puts "-"*50
gems.sort_by{|gem, time| time }.reverse.each do |gem, time|
puts format % [gem, time, (time / total * 100)]
end
puts "-"*50
puts "#{format}\n\n" % ["Total", total, 100]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment