C#性能分析 - 如何计算CPU周期?

Kir*_*ril 2 c# performance casting

这是进行性能分析的有效方法吗?我想获得纳秒精度并确定类型转换的性能:

class PerformanceTest
{
    static double last = 0.0;
    static List<object> numericGenericData = new List<object>();
    static List<double> numericTypedData = new List<double>();

    static void Main(string[] args)
    {
        double totalWithCasting = 0.0;
        double totalWithoutCasting = 0.0;
        for (double d = 0.0; d < 1000000.0; ++d)
        {
            numericGenericData.Add(d);
            numericTypedData.Add(d);
        }
        Stopwatch stopwatch = new Stopwatch();
        for (int i = 0; i < 10; ++i)
        {

            stopwatch.Start();
            testWithTypecasting();
            stopwatch.Stop();
            totalWithCasting += stopwatch.ElapsedTicks;

            stopwatch.Start();
            testWithoutTypeCasting();
            stopwatch.Stop();
            totalWithoutCasting += stopwatch.ElapsedTicks;
        }

        Console.WriteLine("Avg with typecasting = {0}", (totalWithCasting/10));
        Console.WriteLine("Avg without typecasting = {0}", (totalWithoutCasting/10));
        Console.ReadKey();
    }

    static void testWithTypecasting()
    {
        foreach (object o in numericGenericData)
        {
            last = ((double)o*(double)o)/200;
        }
    }

    static void testWithoutTypeCasting()
    {
        foreach (double d in numericTypedData)
        {
            last = (d * d)/200;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Avg with typecasting = 468872.3
Avg without typecasting = 501157.9
Run Code Online (Sandbox Code Playgroud)

我有点怀疑......看起来对性能的影响几乎没有.铸造真的那么便宜吗?

更新:

class PerformanceTest
{
    static double last = 0.0;
    static object[] numericGenericData = new object[100000];
    static double[] numericTypedData = new double[100000];

    static Stopwatch stopwatch = new Stopwatch();
    static double totalWithCasting = 0.0;
    static double totalWithoutCasting = 0.0;
    static void Main(string[] args)
    {
        for (int i = 0; i < 100000; ++i)
        {
            numericGenericData[i] = (double)i;
            numericTypedData[i] = (double)i;
        }

        for (int i = 0; i < 10; ++i)
        {
            stopwatch.Start();
            testWithTypecasting();
            stopwatch.Stop();
            totalWithCasting += stopwatch.ElapsedTicks;
            stopwatch.Reset();

            stopwatch.Start();
            testWithoutTypeCasting();
            stopwatch.Stop();
            totalWithoutCasting += stopwatch.ElapsedTicks;
            stopwatch.Reset();
        }

        Console.WriteLine("Avg with typecasting = {0}", (totalWithCasting/(10.0)));
        Console.WriteLine("Avg without typecasting = {0}", (totalWithoutCasting / (10.0)));
        Console.ReadKey();
    }

    static void testWithTypecasting()
    {
        foreach (object o in numericGenericData)
        {
            last = ((double)o * (double)o) / 200;
        }
    }

    static void testWithoutTypeCasting()
    {
        foreach (double d in numericTypedData)
        {
            last = (d * d) / 200;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Avg with typecasting = 4791
Avg without typecasting = 3303.9
Run Code Online (Sandbox Code Playgroud)

Guf*_*ffa 8

请注意,您测量的不是类型转换,而是取消装箱.这些值一直是双打,没有类型转换.

您忘记在测试之间重置秒表,因此您反复添加所有先前测试的累计时间.如果将刻度转换为实际时间,您会发现它总计比运行测试所花费的时间多得多.

如果你stopwatch.Reset();在每个之前添加一个stopwatch.Start();,你得到一个更合理的结果,如:

Avg with typecasting = 41027,1
Avg without typecasting = 20594,3
Run Code Online (Sandbox Code Playgroud)

取消装箱值并不是那么昂贵,只需要检查对象中的数据类型是否正确,然后获取值.仍然比已知类型的工作要多得多.请记住,您还在测量结果的循环,计算和分配,这两个测试都是相同的.

拳击值比取消装箱更昂贵,因为它在堆上分配一个对象.