2017-10-20 6 views
1

私の現在のコードベースでは、複雑なifステートメントは代行コールで置き換えられることがよくあります。コードの構造のため、同じデリゲートがアプリケーションの過程で何度も呼び出されます。たとえば、パフォーマンス以来C#JITterは繰り返しの代理コールを最適化できますか?

class ExampleClass 
{ 
    private delegate double ExampleDelegate(double x, double y); 
    private ExampleDelegate _exampleMethod; 
    private bool _condition1; 

    ... 

    public double ApiFunction(List<double> a, List<double> b, bool condition2) 
    { 
     if ((_condition1 && !condition2) || getCondition3()) 
     { 
      _exampleMethod = adder; 
     } 
     else 
     { 
      _exampleMethod = subtracter; 
     } 

     double finalResult = 0; 

     for (int i = 0; i < a.Count; i++) 
     { 
      finalResult += _exampleMethod(a[i], b[i]); 
     } 

     return finalResult; 
    } 

    private double adder(double a, double b) 
    { 
     return a + b; 
    } 

    private double subtracter(double a, double b) 
    { 
     return a - b; 
    } 
} 

は、ジッタは、最終的にこれらのメソッドの1つが、すべての時間とインラインで呼び出されていることを認識し、あるいは呼び出しを最適化する場合、私は思ったんだけど、ここで懸念されます。

したがって、は、C#JITterをインライン化するか、繰り返し代理人呼び出しを最適化することができます

+0

デリゲートベースのディスパッチにどのようなヒントがあるのか​​をベンチマークするのはどうでしょうか?また、メソッド群を使うafaikはラムダ式よりも高価ですので、 '_exampleMethod =(a、b)=>加算器(a、b);'を試してみることをお勧めします。しかしもう一度、あなたはperfについて興味がありますか?基準! – MarcinJuraszek

+0

@MarcinJuraszekラムダについてのあなたの発言のように、実際の方法ははるかに複雑で、通常約25行です。後で実際のパフォーマンスへの影響を見るためにいくつかのパフォーマンスベンチマークを行うかもしれませんが、実際のパフォーマンスへの影響だけでなく、技術的に何が起こっているのかも興味があります。ありがとう。 – Defenestrator

+0

@MarcinJuraszek何故同じメソッドを呼び出すだけで、全く同じパラメータを渡し、生産的な作業をしない新しいメソッドを作成する方が効率的だと思いますか? – Servy

答えて

4

これはありません。デリゲート呼び出しは常に間接呼び出しであり、実行時に動的にバインドされます。これは、呼び出しが行われたときに発生します。それだけが、既知のデリゲートオブジェクトの値です。ジッタはその前に実行されます。オプティマイザがそれらを改善するために行うことができるものは何もありません。正確に何が呼び出されるかについては何の知識もありません。それはターゲットメソッドは、インスタンスメソッドまたは静的であるかどうかを知ることができないか

注意、それはインスタンスメソッドを想定しています。コールスタッブを再ジャンギングするために静的な場合は、コールスタブによって余分な作業を行う必要があります。その余分な作業は、x64コードにとっては相当なものです。スニペットで注目すべき点は、静的メソッドは通常、これに注意するより意味があるということです。

最初の呼び出しは、呼び出しスタブを作成し、ターゲット・メソッドがJITコンパイルする必要があるとき、それはだ、高価です。この場合、ジッタはメソッドがどのように見えるかを既に正確に推測しているため、スタブは単なる単一のJMP命令です。これ以降の呼び出しは通常の速度で実行され、通常の呼び出しよりも大幅に遅くなることはありませんが、通常はこれらの小さなメソッドのようにインライン展開を行うことはできません。変更は行われません。.NETはインタプリタを使用しないため、ホットスポットコンパイラのようなものはありません。

あなたは、測定し、これはそう簡単なベンチマークミスを傷つけると測定は非常に一貫性がないであろう傾向が非常に高速なコードであることを用心する必要があります。しかし、あなたが実際のperf問題を発見したときにだけ、それに時間を費やすことを検討してください。それは一般的ではない、代議員は吸いません。

関連する問題