1

メソッドがインライン化されている場合、理論的にはメソッドと呼び出しメソッドのマージと同じであると考えていましたが、ベンチマークではパフォーマンスにわずかな違いがあることが示されました

たとえば、これには100msかかります

    public long TestA()
    {
        long ret = 0;
        for (int n = 0; n < testSize; n++)
        {
            for (int i = 0; i < a; i++)
                for (int j = 0; j < b; j++)
                {
                    ret += myArray[i][j];
                }
        }
        return ret;
    }

これには110ミリ秒かかります(強制MethodImplOptions.NoInliningするGetItと400ミリ秒になるので、自動インライン化されていると思います)

    public long TestB()
    {
        long ret = 0;
        for (int n = 0; n < testSize; n++)
        {
            for (int i = 0; i < a; i++)
                for (int j = 0; j < b; j++)
                {
                    ret += GetIt(i, j);
                }
        }
        return ret;
    }

    int GetIt(int x, int y)
    {
        return myArray[x][y];
    }

OK、使用したベンチマーク関数のスニペットを添付します

    public static void RunTests(Func<long> myTest)
    {
        const int numTrials = 100;
        Stopwatch sw = new Stopwatch();
        double[] sample = new double[numTrials];

        Console.WriteLine("Checksum is {0:N0}", myTest());

        sw.Start();
        myTest();
        sw.Stop();

        Console.WriteLine("Estimated time per test is {0:N0} ticks\n", sw.ElapsedTicks);
        if (sw.ElapsedTicks < 100)
        {
            Console.WriteLine("Ticks per test is less than 100 ticks. Suggest increase testSize.");
            return;
        }

        if (sw.ElapsedTicks > 10000)
        {
            Console.WriteLine("Ticks per test is more than 10,000 ticks. Suggest decrease testSize.");
            return;
        }

        for (int i = 0; i < numTrials / 3; i++)
        {
            myTest();
        }

        string testName = myTest.Method.Name;
        Console.WriteLine("----> Starting benchmark {0}\n", myTest.Method.Name);
        for (int i = 0; i < numTrials; i++)
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();

            sw.Restart();
            myTest();
            sw.Stop();
            sample[i] = sw.ElapsedTicks;
        }
        double testResult = DataSetAnalysis.Report(sample);
        DataSetAnalysis.ConsistencyAnalyze(sample, 0.1);
        Console.WriteLine();

        for (int j = 0; j < numTrials; j = j + 5)
            Console.WriteLine("{0,8:N0} {1,8:N0} {2,8:N0} {3,8:N0} {4,8:N0}", sample[j], sample[j + 1], sample[j + 2], sample[j + 3], sample[j + 4]);
        Console.WriteLine("\n----> End of benchmark");
    } 
4

2 に答える 2

1

結果として得られる IL 命令の数はわずかに異なり、maxstack は大きく異なります。

TestA:
// Code size       78 (0x4e)
.maxstack  2


TestB:
// Code size       88 (0x58)
.maxstack  4

GetIt:
// Code size       7 (0x7)
.maxstack  1
于 2012-09-14T11:33:10.093 に答える
0

C#はJITでインライン化するため、 ILがインラインであるかどうかは変わりません。

MethodImplOptions.NoInlininginlineF#のキーワードと同じではありません

于 2012-09-14T23:10:37.667 に答える