C# 值类型与引用类型-性能

C# 值类型与引用类型-性能,c#,boxing,reference-type,C#,Boxing,Reference Type,我正忙着读乔恩·斯基特的好书。他在关于装箱和拆箱的一节中提到,使用装箱对象的开销很小,可以想象,在足够大的范围内,这会对性能产生影响 所以我编写了自己的基准测试,使用for循环将从1到100000000的所有数字相加。在一个例子中,我使用了Int32,然后使用int,然后我转换到object,再转换回int。重复所有测试10次,取平均值。结果(以秒为单位): Int32平均值:0.333 国际平均值:0.326 对象平均值:1.061 Int32和int之间没有太大区别,但是装箱/拆箱的时间要长

我正忙着读乔恩·斯基特的好书。他在关于装箱和拆箱的一节中提到,使用装箱对象的开销很小,可以想象,在足够大的范围内,这会对性能产生影响

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

Int32平均值:0.333

国际平均值:0.326

对象平均值:1.061

Int32
int
之间没有太大区别,但是装箱/拆箱的时间要长3倍

因此,请帮助我理解:当您将
int
强制转换为
对象
时,是否与将其强制转换为
Int32
相同?断言
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());
const int SIZE=100000000,迭代次数=10;
var intTimes=新列表();
var int32Times=新列表();
var objectTimes=新列表();
对于(var n=0;n
c#关键字
int
System.Int32
的别名。所以他们的表现完全一样

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

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

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

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


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

我们必须查看您的测试。“很可能您没有预热抖动,所以您的第一个抖动将比第二个抖动执行得慢。”KirkWoll基准测试代码添加到问题中。我们必须查看您的测试。“很可能您没有预热抖动,因此您的第一个抖动将比第二个抖动执行得慢。”KirkWoll基准测试代码添加到问题中;每次
int
循环比
Int32
循环快1-5%。你认为这只是巧合吗?是一个程序正在运行,执行所有三个测试,还是修改程序并对一个数据类型运行一个测试?@Shaul这一定是巧合(或者测试代码中存在缺陷)
int
System.Int32
是同义词。它们将产生相同的IL代码(您可以使用Reflector进行验证)。很有趣。我在测试循环中切换了int和Int32,现在Int32稍微快一点。所以你是对的,这与int和Int32的不同无关,而是与启动循环时的某种开销有关@马修沃森-礼貌平。这就是为什么被问到。第一次运行一段代码时,它会第一次执行一些额外的操作,如加载程序集等。这也会产生一些延迟;每次
int
循环比
Int32
循环快1-5%。你认为这只是巧合吗?是一个程序正在运行,执行所有三个测试,还是修改程序并对一个数据类型运行一个测试?@Shaul这一定是巧合(或者测试代码中存在缺陷)
int
System.Int32
是同义词。它们将产生相同的IL代码(您可以使用Reflector进行验证)。很有趣。我在测试循环中切换了int和Int32,现在Int32稍微快一点。所以你是对的,这与int和int32b无关