在.Net中,出于性能原因,我是否应该通过引用传递结构?

时间:2009-01-26 20:58:49

标签: c# .net optimization

在我的C#应用​​程序中,我有一个大型结构(176字节),每秒可能传递一十万次到一个函数。然后,该函数只需要一个指向struct的指针,并将指针传递给非托管代码。函数和非托管代码都不会对结构进行任何修改。

我的问题是,我应该通过值还是通过引用将结构传递给函数?在这种特殊情况下,我的猜测是,通过引用传递比将176个字节推入调用堆栈要快得多,除非JIT碰巧认识到结构永远不会被修改(我的猜测是因为结构体的结构不能识别它)地址被传递给非托管代码)并优化代码。

由于我们正在使用它,让我们回答更常见的情况,其中函数将struct的指针传递给非托管代码,而是对内容执行一些只读操作。结构。通过引用传递结构会更快吗?在这种情况下,JIT会认识到结构永远不会被修改,从而进行优化吗?据推测,通过引用传递一个1字节的结构是更有效,但是如果有的话,通过引用传递结构会变得更好吗?

感谢。

编辑:

如下所述,还可以为常规使用创建“等效”类,然后在传递给非托管代码时使用结构。我在这里看到两个选项:

1)创建一个简单包含结构的“包装器”类,然后在必要时将指向结构的指针传递给非托管代码。我看到的一个潜在问题是钉扎有其自身的性能影响。

2)创建一个等价的类,当需要struct时,其字段被复制到struct。但是复制需要花费很多时间,而且在我看来首先要通过引用来打败它。

编辑:

如下所述,我当然可以衡量每种方法的表现。我执行此操作并发布结果。但是,我仍然有兴趣从知识分子的角度看待人们的答案和推理。

4 个答案:

答案 0 :(得分:9)

我做了一些非常非正式的分析,结果表明,对于我的特定应用程序,通过引用传递的性能提升不大。对于按值,我每秒大约有10,050,000个呼叫,而对于按参考,我每秒大约有11,200,000个呼叫。

您的里程可能会有所不同。

答案 1 :(得分:8)

在你询问是否应该通过引用传递结构之前,你应该问问自己为什么你首先要有这么大的结构。 真的是否需要成为一个结构?如果你需要在某个时候使用一个结构来进行P / Invoke,是否值得为它构建一个struct ,然后在其他地方使用等价的类?

一个非常非常不寻常的结构......

有关此问题的更多指导,请参阅Design Guidelines for Developing Class Libraries上的Choosing Between Classes and Structures部分。

答案 2 :(得分:2)

获得这个问题答案的唯一方法是对两者进行编码并测量性能。

你提到了非托管/托管互操作。我的经验是,互操作需要花费相当长的时间。您可以尝试更改代码:

void ManagedMethod(MyStruct[] items) {
  foreach (var item in items) {
    unmanagedHandle.ProcessOne(item);
  }
}

要:

void ManagedMethod(MyStruct[] items) {
  unmanagedHandle.ProcessMany(items, items.Count);
}

这种技术在类似的情况下帮助了我,但只有测量结果会告诉你它是否适用于你的情况。

答案 3 :(得分:-2)

为什么不直接使用类,并将您的类传递给P / Invoke函数?

使用类将在托管代码中很好地传递,并且与通过引用P / Invoke函数传递结构相同。

e.g。

// What you have
public struct X
{
   public int data;
}
[DllImport("mylib.dll")]
static extern void Foo( ref X arg);

// What you could do
[StructLayout(LayoutKind.Sequential)]
public class Y
{
    public int data;
}
[DllImport("mylib.dll")]
static extern void Bar( Y arg );