值类型与引用类型 - 性能

时间:2013-05-01 17:38:48

标签: c# boxing reference-type

我正忙着读Jon Skeet的优秀书C# In Depth。他在关于装箱和拆箱的部分中提到,使用盒装对象的开销很小,可以在很大的范围内产生性能差异。

所以我编写了自己的基准测试,使用for循环将所有数字从1到100,000,000加在一起。在一个案例中,我使用Int32,然后使用int,然后转换为object并转回int。重复所有测试10次并取平均值。结果(以秒为单位):

  

Int32 avg:0.333

     

int avg:0.326

     

对象平均值:1.061

Int32int之间差别不大,但拳击/拆箱时间要长3倍!

所以请在此帮助我理解:当您将int投射到object时,是不是将其投放到Int32DotNetPerls断言int实际上只是Int32的别名 - 但如果是这种情况,那么为什么int的执行速度始终高于Int32,即使只是略有不同?

编辑:根据热门请求,这是基准代码:

const int SIZE = 100000000, ITERATIONS=10;
var intTimes = new List<double>();
var int32Times = new List<double>();
var objectTimes = new List<double>();

for (var n = 0; n < ITERATIONS; n++)
{
    Console.WriteLine("Iteration "+(n+1));
    Console.WriteLine("Testing using Int32");
    long result = 0;
    var sw = Stopwatch.StartNew();
    for (Int32 x = 0; x < SIZE; x++)
    {
        result += x;
    }
    sw.Stop();
    int32Times.Add(sw.Elapsed.TotalSeconds);
    Console.WriteLine("Result = {0} after {1:0.000} seconds", result, sw.Elapsed.TotalSeconds);

    Console.WriteLine("Testing using int");
    result = 0;
    sw = Stopwatch.StartNew();
    for (int x = 0; x < SIZE; x++)
    {
        result += x;
    }
    sw.Stop();
    Console.WriteLine("Result = {0} after {1:0.000} seconds", result, sw.Elapsed.TotalSeconds);
    intTimes.Add(sw.Elapsed.TotalSeconds);

    Console.WriteLine("Testing using object");
    result = 0;
    sw = Stopwatch.StartNew();
    for (int i = 0; i < SIZE; i++)
    {
        object o = i;
        result += (int) o;
    }
    sw.Stop();
    Console.WriteLine("Result = {0} after {1:0.000} seconds", result, sw.Elapsed.TotalSeconds);
    objectTimes.Add(sw.Elapsed.TotalSeconds);
}
Console.WriteLine("Summary:");
Console.WriteLine("Int32 avg: {0:0.000}", int32Times.Average());
Console.WriteLine("int avg: {0:0.000}", intTimes.Average());
Console.WriteLine("object avg: {0:0.000}", objectTimes.Average());

1 个答案:

答案 0 :(得分:3)

c#关键字intSystem.Int32的别名。所以表演完全一样。

当然,测量过程中总会出现波动,因为您的机器也在执行其他任务。

每次将int强制转换为object时,保留一小块内存(在堆上),并将int的值复制到那里。这需要相当多的努力。每次将其强制转换时,.NET将首先检查您的对象是否实际包含int(因为对象可以包含任何内容),然后将值复制回int。这项检查也需要时间。