gpt4 book ai didi

c# - 结构数组与对象数组 C#

转载 作者:太空狗 更新时间:2023-10-30 00:10:06 28 4
gpt4 key购买 nike

我知道可变结构是邪恶的。但是,我仍然想比较结构数组与对象数组的性能。这是我目前所拥有的

 public struct HelloStruct
{
public int[] hello1;
public int[] hello2;
public int hello3;
public int hello4;
public byte[] hello5;
public byte[] hello6;
public string hello7;
public string hello8;
public string hello9;
public SomeOtherStruct[] hello10;

}

public struct SomeOtherStruct
{
public int yoyo;
public int yiggityyo;
}

public class HelloClass
{
public int[] hello1;
public int[] hello2;
public int hello3;
public int hello4;
public byte[] hello5;
public byte[] hello6;
public string hello7;
public string hello8;
public string hello9;
public SomeOtherClass[] hello10;

}
public class SomeOtherClass
{
public int yoyo;
public int yiggityyo;
}

static void compareTimesClassVsStruct()
{
HelloStruct[] a = new HelloStruct[50];
for (int i = 0; i < a.Length; i++)
{
a[i] = default(HelloStruct);
}

HelloClass[] b = new HelloClass[50];
for (int i = 0; i < b.Length; i++)
{
b[i] = new HelloClass();
}
Console.WriteLine("Starting now");
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
a[i % 50].hello1 = new int[] { 1, 2, 3, 4, i % 50 };
a[i % 50].hello3 = i;
a[i % 50].hello7 = (i % 100).ToString();
}
s1.Stop();

var s2 = Stopwatch.StartNew();
for (int j = 0; j < _max; j++)
{
b[j % 50].hello1 = new int[] { 1, 2, 3, 4, j % 50 };
b[j % 50].hello3 = j;
b[j % 50].hello7 = (j % 100).ToString();
}
s2.Stop();

Console.WriteLine(((double)(s1.Elapsed.TotalSeconds)));
Console.WriteLine(((double)(s2.Elapsed.TotalSeconds)));
Console.Read();

}

我想了解这里发生的一些事情。

首先,由于数组存储结构,当我尝试使用索引操作从数组访问结构时,我应该获取结构的副本还是对原始结构的引用?在这种情况下,当我在运行代码后检查数组时,我得到了变异的结构值。为什么会这样?

其次,当我比较 CompareTimesClassVsStruct() 中的计时时,我得到的时间大致相同。这背后的原因是什么?在任何情况下,使用结构数组或对象数组会优于另一个吗?

谢谢

最佳答案

当您访问结构数组元素的属性时,您并不是在操作该结构的副本 - 您是在操作该结构本身。 (这不是 List<SomeStruct>,您将在副本上操作,示例中的代码甚至无法编译。)

您看到相似时间的原因是时间被 (j % 100).ToString() 扭曲了。和 new int[] { 1, 2, 3, 4, j % 50 };在循环内。这两个语句所花费的时间使数组元素访问所花费的时间相形见绌。

我稍微更改了测试应用程序,我得到了访问 9.3 秒的结构数组和 10 秒的类数组的时间(1,000,000,000 次循环),因此结构数组明显更快,但速度非常快。

可以使结构数组更快迭代的一件事是引用的局部性。迭代结构数组时,相邻元素在内存中相邻,这减少了处理器缓存未命中的次数。

类数组的元素不相邻(尽管对数组中元素的引用当然是相邻的),这会导致在遍历数组时更多的处理器缓存未命中。

另一件需要注意的事情是结构数组中的连续字节数实际上是 (number of elements) * (sizeof(element)) ,而类数组中的连续字节数是 (number of elements) * (sizeof(reference))其中引用的大小为 32 位或 64 位,具体取决于内存模型。

这可能是大型结构数组的问题,其中数组的总大小超过 2^31 字节。

您可能会看到的另一个速度差异是将大型结构作为参数传递时 - 显然,按值传递对堆栈上引用类型的引用的副本比按值传递一个大结构的副本要快得多结构。

最后,请注意您的示例结构不是很有代表性。它包含很多引用类型,所有这些都将存储在堆上的某个位置,而不是数组本身。

根据经验,结构的大小不应超过 32 字节左右(确切的限制是有争议的),它们应该只包含原始(blittable)类型,并且它们应该是不可变的。而且,通常情况下,您无论如何都不应该担心将事物变成结构体,除非您对它们有可证明的性能需求。

关于c# - 结构数组与对象数组 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35654689/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com