值类型与引用类型-性能

本文关键字:性能 引用类型 类型 | 更新日期: 2023-09-27 18:11:46

我正忙于阅读Jon Skeet的优秀著作《深度C#》。他在关于装箱和开箱的章节中提到,使用装箱对象的开销很小,可以想象会在足够大的范围内产生性能差异。

因此,我编写了自己的基准测试,使用for循环将从1到100000000的所有数字相加。在一种情况下,我使用Int32,然后使用int,然后转换为object,再转换回int。将所有测试重复10次,取平均值。结果(以秒为单位(:

Int32平均值:0.333

int平均值:0.326

对象平均值:1.061

Int32int没有太大区别,但装箱/拆箱的时间要长3倍!

所以请帮我理解一下:当你把int转换成object时,这不是和把它转换成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());

值类型与引用类型-性能

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

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

每次将int强制转换为object时,都会保留一小块内存(堆上(,并将int的值复制到其中。这需要付出相当大的努力。每次将其强制转换回时,.NET将首先检查对象是否真的包含int(因为对象可以包含任何内容(,然后将值复制回int。此检查也需要时间。