2013-05-01 84 views
0

我正在阅读Jon Skeet的优秀书籍C# In Depth。他在关于装箱和拆箱的部分中提到,使用盒装物品的开销很小,可以在一个足够大的规模上实现性能差异。数值类型与参考类型 - 性能

因此,我编写了自己的基准测试,使用for循环将所有数字从1增加到100,000,000。在一种情况下,我使用Int32,然后int,然后我投到object并退回到int。重复所有测试10次并取平均值。结果(以秒计):

的Int32平均:0.333

INT平均:0.326

对象平均:Int32int之间1.061

没有太大的差别,但拳击/拆箱花了3倍!

所以请帮我理解一下:当你投intobject时,是不是和把它投到Int32一样? DotNetPerls声称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()); 
+3

我们将不得不看你的测试。最有可能的是你没有让抖动变得温暖,所以你的第一个人的表现会比第二个人慢。 – 2013-05-01 17:42:00

+0

@KirkWoll基准代码添加到问题。 – 2013-05-01 18:00:30

回答

3

C#的关键字intSystem.Int32的别名。所以执行完全一样。

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

每次将int转换为object时,只留下一小部分内存(在堆上),并将int的值复制到那里。这需要很多努力。每次你将它抛出去,比.NET首先检查你的对象是否实际上包含了一个int(因为一个对象可以包含任何东西),然后将值复制回int。这项检查也需要时间。

+0

我跑了几次基准;每次'int'循环比'Int32'循环快,在1-5%之间。你认为那只是巧合? – 2013-05-01 17:43:05

+1

这是你正在运行的一个程序做三个测试还是你修改程序并为一个数据类型运行一个测试? – 2013-05-01 17:44:13

+1

@Shaul它必须是巧合(或测试代码中的缺陷)。 'int'和'System.Int32'是*同义词*。他们将产生相同的IL代码(您可以使用Reflector进行验证)。 – 2013-05-01 17:52:43