I have a Rails 2.3.10 app with bundler. At startup the memory footprint is quite big (300MB in development mode).
I would like to see how much memory each gem takes on startup.
We had a problem in which our basic Rails app, with no traffic or requests, had a footprint of ~140MB on startup.
We used the following approach to trace the memory requirement of each gem specified in the Gemfile of our app, without having to try to patch bundler.
rails new myappname
generate a new empty rails appbundle install
and then rails server
to ensure it is possible to boot up the rails server and that any basic configurations required are loadedrequire: false
at the end of each line. Ensure that any other gems that are specified with one name but required using :require => 'othergemname' are using the older ruby Hash notation so that the pattern match below will catch it.bundle install
again to regenerate the Gemfile.lockCreate the following script which will use manually require each gem specified in the Gemfile and log the system memory consumed by the rails process before and after.
# require_and_profile.rb
def require_and_profile(gemname = nil)
unless gemname
puts "%-20s: %10s | %10s" % ['gem','increment','total']
return
end
# This is how to get memory of calling process in OS X, check host OS for variants
memory_usage = `ps -o rss= -p #{Process.pid}`.to_i / 1024.0
require gemname
puts "%-20s: %10.2f | %10.2f" % [ gemname, (`ps -o rss= -p #{Process.pid}`.to_i / 1024.0 - memory_usage), (`ps -o rss= -p #{Process.pid}`.to_i / 1024.0)]
end
pattern = /^[^#]*gem[ ]*['"]([^,'"]*)['"][ ,~>0-9\.'"]*(:require[ => ]*['"]([^'"]*)['"][, ])?/
require_and_profile
File.open('Gemfile').each do |line|
if line.match(pattern)
if line.match(pattern)[3]
require_and_profile line.match(pattern)[3]
else
require_and_profile line.match(pattern)[1]
end
end
end
Run rails c
load 'require_and_profile.rb'
This helped us identify for example, that we'd been requiring asset-sync in our boot when we only needed it in the :asset group. We do find that on different boot-ups the memory footprint of each gem is not exactly the same, but running it a few times does show you the patterns of which ones are the memory-hungry gems.
There is an easier way to do this now with the derailed gem:
add to your gemfile:
gem 'derailed', group: :development
then on the command line from your apps root:
bundle exec derailed bundle:mem
This will print out how much memory each gem takes as it's included.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With