1

spec コードの実行に予想以上に時間がかかるという問題がありましたが、 で実行しようとするとrspec-prof、問題が解決したように見えました。rake最終的に、ネイティブで実行することと、インタープリターで実行することとの違いを追跡しました。

ランニングにはわずかrake75 秒しかかかりませんが、ランニングruby $(which rake)にはわずか 12 秒しかかかりません。その速度は5 倍以上です。見てみましょう:

$ 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

「ラッパー バイナリ」の内容を見るとrake、「#!」で示されます。インタープリターの下で実行されている行ruby_noexec_wrapper--そして、コマンドを次のように実行するのに十分です:

ruby_noexec_wrapper $(which rake)

同じようにゆっくりと 75 秒走ります。

これが当てはまる理由はありますか?

rake を直接実行するのを避ける以外に、それを改善するためにできることはありますか? これは gem をバイナリにラップする標準的な方法であるため、gem でパッケージ化されたすべてのツールの速度が低下する可能性はありませんか?

4

1 に答える 1

1

ruby_noexec_wrapperファイル (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

私が見る限り、2 つの警告領域は 2 つのrequireステートメントです。require 'rubygems'Ruby 1.9+ではこれが自動的に行われるため、最初のは問題になる可能性は低いです。

問題は にあると思いますrequire 'rubygems-bundler/noexec'。それが何をしているのかを見ると、バンドラーをセットアップしていることがわかります。これには gem が必要であり、起動が遅くなる原因となる可能性があります。

Gem は、ロードされたときに多くのことを行うべきではありませんが、残念ながら、それらの多くはその領域でいくつかの間違いを犯します。これを解決する唯一の方法は、速度低下の大部分を引き起こしている gem を特定し、可能な場合は代替手段を見つけることです。

于 2013-03-22T15:45:01.657 に答える