C#的性能分析 - 如何计算CPU周期? [英] C# performance analysis- how to count CPU cycles?

查看:90
本文介绍了C#的性能分析 - 如何计算CPU周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 类PerformanceTest 
{
静态双最后= 0.0;
静态列表<对象> numericGenericData =新的List<对象>();
静态列表<双> numericTypedData =新的List<双>();

静态无效的主要(字串[] args)
{
双totalWithCasting = 0.0;
双totalWithoutCasting = 0.0;
的(双D = 0.0; D< 1000000.0; ++ D)
{
numericGenericData.Add(D);
numericTypedData.Add(四);
}
秒表=新的秒表();
的for(int i = 0;我小于10; ++ I)
{

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

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

Console.WriteLine(平均类型转换= {0}(totalWithCasting / 10));
Console.WriteLine(平均无铸字= {0}(totalWithoutCasting / 10));
Console.ReadKey();
}

静态无效testWithTypecasting()
{
的foreach(对象o在numericGenericData)
{
最后=((双)O *(双)O)/ 200;
}
}

静态无效testWithoutTypeCasting()
{
的foreach(在numericTypedData双D)
{
最后= (D * D)/ 200;
}
}
}



输出是:

 均价= 501157.9 
p $ p>

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



更新:



 类PerformanceTest 
{
静态双重最后= 0.0;
静态对象[] = numericGenericData新的对象[100000]。
静态双重[] = numericTypedData新的双[100000]。

静态秒表=新的秒表();
静态双totalWithCasting = 0.0;
静态双totalWithoutCasting = 0.0;
静态无效的主要(字串[] args)
{
的for(int i = 0; I< 100000; ++ I)
{
numericGenericData [我] =(双)我;
numericTypedData [I] =(双)我;
}

表示(INT I = 0; I&小于10 ++ⅰ)
{
stopwatch.Start();
testWithTypecasting();
stopwatch.Stop();
totalWithCasting + = stopwatch.ElapsedTicks;
stopwatch.Reset();

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

Console.WriteLine(平均类型转换= {0}(totalWithCasting /(10.0)));
Console.WriteLine(平均无铸字= {0}(totalWithoutCasting /(10.0)));
Console.ReadKey();
}

静态无效testWithTypecasting()
{
的foreach(对象o在numericGenericData)
{
最后=((双)O *(双)O)/ 200;
}
}

静态无效testWithoutTypeCasting()
{
的foreach(在numericTypedData双D)
{
最后= (D * D)/ 200;
}
}
}



输出是:

    p $ p> 
解决方案

请注意,它不是类型转换,你是测量,它的拆箱。这些值是双打,一直以来,没有类型转换正在进行。



您忘了重新测试之间的秒表,所以您要添加的所有先前测试的累计时间一遍又一遍。如果转换蜱实际的时候,你看到它加起来比它花了运行测试的时间多得多。



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

 平均类型转换= 41027,1 
平均无铸字= 20594,3

拆箱值不那么贵,它只有检查对象中的数据类型是正确的,那么获得的价值。它仍然是当类型是已知比很多工作。请记住,您也测量循环,计算和的结果,这是对两个试验相同的分配



拳击值小于拆箱更昂贵,因为该分配在堆上的一个对象。


Is this a valid way to do performance analysis? I want to get nanosecond accuracy and determine the performance of typecasting:

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;
        }
    }
}

The output is:

Avg with typecasting = 468872.3
Avg without typecasting = 501157.9

I'm a little suspicious... it looks like there is nearly no impact on the performance. Is casting really that cheap?

Update:

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;
        }
    }
}

The output is:

Avg with typecasting = 4791
Avg without typecasting = 3303.9

解决方案

Note that it's not typecasting that you are measuring, it's unboxing. The values are doubles all along, there is no type casting going on.

You forgot to reset the stopwatch between tests, so you are adding the accumulated time of all previous tests over and over. If you convert the ticks to actual time, you see that it adds up to much more than the time it took to run the test.

If you add a stopwatch.Reset(); before each stopwatch.Start();, you get a much more reasonable result like:

Avg with typecasting = 41027,1
Avg without typecasting = 20594,3

Unboxing a value is not so expensive, it only has to check that the data type in the object is correct, then get the value. Still it's a lot more work than when the type is already known. Remember that you are also measuring the looping, calculation and assigning of the result, which is the same for both tests.

Boxing a value is more expensive than unboxing it, as that allocates an object on the heap.

这篇关于C#的性能分析 - 如何计算CPU周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆