我正在使用C#/ XNA中的一段代码,我非常关注性能。部分原因是将存储在数组中的几个结构传递给各种函数。
在被问到之前,这些确实应该是结构,而不是类。它们本质上是值类型,它们需要(基本上)存在于堆栈中。它们中有很多,它们来得非常快,并且为它们提供垃圾收集器(即使我在运行池)也会很昂贵。
我已经通过引用传递了相当多的性能,但是我想知道当数组的相同索引处的相同结构通过引用传递给几个不同的函数时,性能的影响是什么。我假设为了使这一切能够完成所有工作,C#必须在传递结构之前在内部固定数组指针。我会先通过固定结构并传递指针来获得性能吗?
例如。如果我有类似的东西:
for(int i = 0; i < array.Length; ++i)
{
value = Function1(ref array[i]);
// Lots of code....
otherValue = Function2(ref array[i]);
// Lots of code....
anotherValue = Function3(ref array[i]);
}
C#基本上不必这样做吗?
for(int i = 0; i < array.Length; ++i)
{
pin(array);
value = Function1(ref array[i]);
unpin(array);
// Lots of code....
pin(array);
otherValue = Function2(ref array[i]);
unpin(array);
// Lots of code....
pin(array);
anotherValue = Function3(ref array[i]);
unpin(array);
}
这样做会更好吗?
for(int i = 0; i < array.Length; ++i)
{
fixed(struct* working = ^array[i])
{
value = Function1(working);
// Lots of code....
otherValue = Function2(working);
// Lots of code....
anotherValue = Function3(working);
}
}
或者,甚至更好,
fixed(struct* working = ^array[0])
{
for(int i = 0; i < array.Length; ++i)
{
value = Function1(working[i]);
// Lots of code....
otherValue = Function2(working[i]);
// Lots of code....
anotherValue = Function3(working[i]);
}
}
或者C#编译器/ JITter是否足够自动固定数组?
答案 0 :(得分:11)
您使用指针混淆了托管引用。
管理引用永远不需要固定,即使它指向数组中的元素,因为GC“知道”引用并在数组移动时更新它。
只有非安全代码中的非托管指针才需要固定,并且出于性能原因应尽可能避免使用。
答案 1 :(得分:0)
我不确定XNA(它是一个不同的CLR),但.NET Framework(从3.5开始)不会引用通过引用传递的东西(默认情况下,除非它们被传递给非托管代码。如果GC被调用,它仍然可以移动数据,因为扫描堆栈是为了引用。如果在某个级别上有非托管代码,那么,是的,它确实需要固定。