Reputation: 2719
I'd been having problems with my spec code taking a lot longer than expected to run, but when I tried to run them under rspec-prof
, the problem seemed to go away. Eventually I tracked the difference down to running rake
natively compare to running it under an interpreter.
Running just rake
takes 75 seconds, but running ruby $(which rake)
takes only 12 seconds. That's over five times as quicker. Take a look:
$ rake
~/.rvm/rubies/ruby-1.9.2-p320/bin/ruby -w -S rspec spec/args_spec.rb spec/levels_spec.rb spec/opts_spec.rb spec/run_spec.rb spec/split_spec.rb spec/unit_spec.rb
~/.rvm/gems/ruby-1.9.2-p320/gems/bundler-1.2.3/lib/bundler/source.rb:516: warning: method redefined; discarding old revision
..................................................
Finished in 1 minute 14.39 seconds
50 examples, 0 failures
$ ruby `which rake`
~/.rvm/rubies/ruby-1.9.2-p320/bin/ruby -w -S rspec spec/args_spec.rb spec/levels_spec.rb spec/opts_spec.rb spec/run_spec.rb spec/split_spec.rb spec/unit_spec.rb
..................................................
Finished in 12.88 seconds
50 examples, 0 failures
Looking at the contents of the rake
"wrapper binary" shows in the "#!" line that it is running under the interpreter - ruby_noexec_wrapper
- and sure enough running the command as:
ruby_noexec_wrapper $(which rake)
Gives the same slow 75 seconds run.
Any ideas why this should be the case?
Apart from avoiding running rake directly is there anything that can be done to improve it? Since that's a standard way to wrap gems to be binaries, isn't that potentially slowing down all gem-packaged tools?
Upvotes: 1
Views: 189
Reputation: 11951
Let's take a look at the ruby_noexec_wrapper
file (rvm 1.16.17):
#!/usr/bin/env ruby
original_file=ARGV[0]
ARGV.shift
$PROGRAM_NAME=original_file
require 'rubygems'
begin
require 'rubygems-bundler/noexec'
rescue LoadError
warn "unable to load rubygems-bundler/noexec" if ENV.key?('NOEXEC_DEBUG')
end
eval File.read(original_file), binding, original_file
As far as I can see, the two warning areas are the two require
statements. The first, require 'rubygems'
, is not likely to be a problem, as ruby 1.9+ does this automatically.
I think the problem is in require 'rubygems-bundler/noexec'
. If you take a look at what it's doing you can see that it's setting up bundler. This involves requiring gems, which is likely to be the source of your slow startup.
Gems shouldn't do a whole lot when they are loaded, but unfortunately many of them make some mistakes in that area. The only way to solve this is to try and work out which gems are causing the majority of the slowness and find alternatives where possible.
Upvotes: 1