Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyでのベンチマークの例外-うん、遅い。

私はいつも、他のフロー制御メカニズムと比較して、ルビーでは例外が遅いだろうと強く思っていました。結局のところ、例外は単純な「ブレーク」や「リターン」よりもはるかに複雑です。でも、以前は自分の勘が間違っていたので、試してみようと思いました。

以下のコードでは、benchmark-ips gemを使用して、例外、ブレーク、およびリターンを介してループを終了する相対的なパフォーマンスを比較しています。私はmri1.9でこのようなベンチマークを行っている人々のウェブ上の例を見てきました。しかし、私はmri2.2で試してみたかったのです。

require 'benchmark/ips'

def exit_via_exception
  5.times do 
    raise RuntimeError
  end
rescue
end

def exit_via_break
  5.times do 
    break
  end
end

def exit_via_return
  5.times do 
    return
  end
end

Benchmark.ips do |x|
  x.report("exception") {  exit_via_exception }
  x.report("break") {  exit_via_break }
  x.report("return") {  exit_via_return }
end

結果はかなり驚異的です。例外を使用する関数は、breakandreturnを使用する関数の半分未満の速度です。

$ ruby exception_benchmark.rb
Calculating -------------------------------------
           exception    50.872k i/100ms
               break   125.322k i/100ms
              return   124.173k i/100ms
-------------------------------------------------
           exception    714.795k (± 2.7%) i/s -      3.612M
               break      3.459M (± 3.1%) i/s -     17.294M
              return      3.379M (± 3.0%) i/s -     16.888M
これは完璧なベンチマークではありません

補償方法がわからない問題がいくつかあります。たとえば、exceptionメソッドとbreakメソッドを返す必要があります。したがって、彼らは単に戻るメソッド以上のことをしています。また、例外を救済することでパフォーマンスのオーバーヘッドが増えるかどうかも知りたいと思います。ただし、レスキューしないとベンチマークが中止されます。

それでも、例外は他の例よりもはるかに遅いので、完璧でなくても結果には意味があると思います。

私たちが学んだ教訓は?

フロー制御メカニズムとして例外を使用している場合。今やめて!特に、例外が何度も発生してキャッチされるループがある場合。

これにより、私が個人的に例外を使用する方法が変わりますか?おそらくそうではありません。遅さがルールの例外であるならば、私は少し遅さで生きることができます。 :)

...しかし、JRubyとRBxはどうですか?

Josh Cheek(Twitterの@josh_cheek)は、このベンチマークの独自のバージョンを作成しました。これは、私のものよりも包括的です。そして、彼はそれを複数のルビーの実装に対して実行しました。ここで彼の結果を見ることができます。どうやら休憩はまだ勝者です。 :)


  1. Rubyのカスタム例外

    Rubyで独自の例外を作成するのは簡単です。次の手順に従ってください: 1。新しいクラスを作成する 例外は、Rubyの他のすべてと同じように、クラスです。新しい種類の例外を作成するには、StandardErrorまたはその子の1つから継承するクラスを作成するだけです。 class MyError < StandardError end raise MyError 慣例により、新しい例外のクラス名は「エラー」で終わります。カスタム例外をモジュール内に配置することもお勧めします。つまり、最終的なエラークラスは次のようになります:ActiveRecord::RecordNotFound

  2. Rubyで例外にコンテキストデータを追加する方法

    標準のバックトレース/エラーメッセージの組み合わせでは不十分な場合があります。エラーの原因を特定するために、追加のデータが必要になる場合があります。幸い、Rubyで行うのはとても簡単です。 エラーメッセージのカスタマイズ エラーにコンテキスト情報を追加する最も簡単な方法は、それを例外のメッセージに追加することです。以下の例では、例外をキャッチし、新しいメッセージで再発生させています: begin raise foo rescue => e raise e.class, bar end # RuntimeError: bar このアプローチの良い使用例は、テンプレートをレン