0

DataStructure 呼び出しを単純にラップすると、AggressiveInlining の効果を確認できません

例えば:

public class WList
{
   //made static just to check inlining
   //otherwise inlining might not kick in since 'this' keyword will disallow it
   static System.Collections.ArrayList list;

   [MethodImpl(MethodImplOptions.AggressiveInlining)]
   public override void Put(object item)
   {
       WList.list.Add(item);
   }
}

そして、これを行います

    //Add 1000000 number of items in the list
    //Run this test many times 
    for (int j = 0; j < 100; j++)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();

        for (int i = 0; i < length; i++)
        {
            //ADD ITEMS IN A SIMPLE ARRAY LIST
            arraylist.Add(emptyobject);
        }

        sw.Stop();
        //clear the list
    }

    //Do similar test on wrapper
    for (int j = 0; j < 100; j++)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();

        for (int i = 0; i < length; i++)
        {
            //ADD ITEMS IN ARRAY LIST THROUGH WRAPPER
            wrapperList.Put(emptyobject);
        }

        sw.Stop();
        //clear the list
    }

Inlinig は基本的に関数をアンラップし、内部コードを外部に配置することになっていますが、ラッパーから得られる数値は直接呼び出しよりも遅くなります。

Hastable が使用されている場合、または add の代わりに get 呼び出しが使用されている場合、数値は同じままです。

関数呼び出しのパフォーマンス コストはそのままです。

4

2 に答える 2

5

ストップウォッチは、コードがインライン化されているかどうかを評価するための正しいツールではありません。パフォーマンス メトリックを提供するだけです。

まず、コードをインライン化するには、最適化を有効にしてビルドを実行する必要があります。Visual Studio でこれを行う最も簡単な方法は、リリース ビルドを使用することです。デバッグ ビルドは JITter によって最適化されないため、何もインライン化されません。コードが JITter によってインライン化されているかどうかを確認するには、デバッガーをアタッチして、デバッグ ビルドとリリース ビルドの逆アセンブリを比較することをお勧めします。呼び出しがインライン化されている場合、違いに気付くでしょう。

あなたの例では、にcall対応するアセンブリ命令WList.Put()はリリースビルドで消え、に対応callするアセンブリ命令に置き換えられArrayList.Add()ます。

既定では、Visual Studio デバッガーを任意のビルドにアタッチすると、コードの各行を正しくステップ実行できるように最適化が抑制されることに注意してください。これをオフにするには、[ツール] -> [オプション] -> [デバッグ] -> [全般] にある [モジュールのロード時に JIT 最適化を抑制する] オプションのチェックを外す必要があります。

第二に、あなたの実際の質問に答えるために。メソッドは仮想であるため、インライン化されません。下記のブログ記事を参考にしてください。

http://blogs.msdn.com/b/davidnotario/archive/2004/11/01/250398.aspx

「これらは、メソッドをインライン化しない理由の一部です:

  • 仮想呼び出し: 仮想呼び出し間でインライン化しません。これを行わない理由は、呼び出しの最終的なターゲットがわからないためです。ここでもっとうまくやれる可能性があります (たとえば、呼び出しの 99% が同じターゲットで終了する場合、仮想呼び出しが実行されるオブジェクトのメソッド テーブルをチェックするコードを生成できます。 99% の場合、呼び出しを行い、それ以外の場合はインライン コードを実行するだけです)。ただし、J 言語とは異なり、サポートしている主要言語の呼び出しのほとんどは仮想的ではないため、それほど積極的になる必要はありません。このケースを最適化します。」

この投稿はほぼ 10 年前のものですが、これが後の JIT コンパイラーで変わったとは思いません。

于 2013-07-25T08:07:09.123 に答える