C# 结构与类性能测试

C# 结构与类性能测试,c#,performance,class,struct,C#,Performance,Class,Struct,我构建了一个测试,得到了以下结果: 分配类:15.3260622,分配结构:14.7216018 当分配结构而不是类时,似乎有4%的优势。这很酷,但是添加语言值类型真的足够了吗?我在哪里可以找到一个例子,它表明结构确实优于类 void Main() { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); for (int i = 0; i < 100000000; i++)

我构建了一个测试,得到了以下结果:

分配类:15.3260622,分配结构:14.7216018

当分配结构而不是类时,似乎有4%的优势。这很酷,但是添加语言值类型真的足够了吗?我在哪里可以找到一个例子,它表明结构确实优于类

void Main()
{
    var stopWatch = new System.Diagnostics.Stopwatch();

    stopWatch.Start();

    for (int i = 0; i < 100000000; i++)
    {
        var foo = new refFoo()
        {
            Str = "Alex" + i
        };
    }

    stopWatch.Stop();

    stopWatch.Dump();

    stopWatch.Restart();

    for (int i = 0; i < 100000000; i++)
    {
        var foo = new valFoo()
        {
            Str = "Alex" + i
        };
    }

    stopWatch.Stop();

    stopWatch.Dump();


}

public struct valFoo
{
    public string Str;
}

public class refFoo
{
    public string Str;
}
void Main()
{
var stopWatch=new System.Diagnostics.stopWatch();
秒表。开始();
对于(int i=0;i<100000000;i++)
{
var foo=new refFoo()
{
Str=“Alex”+i
};
}
秒表;
秒表。转储();
stopWatch.Restart();
对于(int i=0;i<100000000;i++)
{
var foo=new valFoo()
{
Str=“Alex”+i
};
}
秒表;
秒表。转储();
}
公共结构valFoo
{
公共字符串Str;
}
公共类refFoo
{
公共字符串Str;
}

您的方法是错误的。您主要测量字符串分配、整数到字符串的转换以及字符串的串联。这个基准不值得写它

为了了解结构的好处,请比较分配1000个对象的数组和分配1000个结构的数组。对于对象数组,需要为数组本身分配一次,然后为数组中的每个对象分配一次。对于结构数组,您有一个结构数组的分配

另外,看看.Net集合的C#源代码中List类的枚举器的实现。它被声明为一个结构。这是因为它只包含一个int,所以整个枚举器结构适合于一个机器字,所以它非常便宜。

尝试一些更简单的测试:

int size = 1000000;
var listA = new List<int>(size);
for (int i = 0; i < size; i++)
    listA.Add(i);

var listB = new List<object>(size);
for (int i = 0; i < size; i++)
    listB.Add(i);
int size=1000000;
var listA=新列表(大小);
对于(int i=0;i

为了在第一种情况下存储1000000个整数,系统分配4000000字节。第二,如果我没弄错的话——大约12000000字节。我怀疑性能差异会更大。

尝试删除在两个测试中执行的100000000个字符串连接。这些几乎肯定是代码中压倒性的因素。我自己也尝试过,在我的机器上,大约95%的基准测试时间都是字符串连接。只需注释掉每种情况下的
Str=
行(或将值更改为常量)。无论如何,我不建议使用公共字段或可变结构。这不仅仅是关于分配。垃圾收集呢?当你的类型逻辑上表示一个值时,你应该使用一个值类型,当你的类型逻辑上表示一个值时,你应该使用一个类。@Servy-sure,但如果我想提高我的应用程序的性能,我想比这个假设更深入一点。你在这里不是比较结构和类,而是比较结构和装箱结构,@RonanThibaudau有道理。(起初我误解了他的意思。)@MikeNakis泛型允许
列表
在存储值时避免装箱,方法是将值类型指定为泛型参数。如果您不这样做,并且将
对象
作为
列表
的类型,则在将值类型放入列表时需要将其装箱。@Servy yes,这是正确的。起初我以为罗南在谈论别的事情。所以,我删除了我之前的评论。@RonanThibaudau拳击存在的唯一原因是结构。如果没有结构,为什么我们需要装箱呢?而且即使他按照你的建议做了,他仍然只会检查分配性能,这是性能与实际使用类型的一个小方面。