在.Net中,出于性能原因,我是否应该通过引用传递结构?
在我的C#应用程序中,我有一个大型结构(176字节),每秒可能传递一十万次到一个函数。 然后,该函数只需要一个指向struct的指针,并将指针传递给非托管代码。 函数和非托管代码都不会对结构进行任何修改。
我的问题是,我应该通过值或引用将结构传递给函数吗? 在这种特殊情况下,我的猜测是,通过引用传递比将176个字节推入调用堆栈要快得多,除非JIT碰巧认识到结构永远不会被修改(我的猜测是因为结构体的结构不能识别它)地址被传递给非托管代码)并优化代码。
既然我们正在使用它,那么我们还要回答更常见的情况,即函数没有将struct的指针传递给非托管代码,而是对struct的内容执行一些只读操作。 通过引用传递结构会更快吗? 在这种情况下,JIT会认识到结构永远不会被修改,从而进行优化吗? 据推测,通过引用传递1字节结构并不是更有效,但是如果有的话,通过引用传递结构会变得更好吗?
谢谢。
编辑:
如下所述,还可以为常规使用创建“等效”类,然后在传递给非托管代码时使用结构。 我在这里看到两个选项:
1)创建一个简单包含结构的“包装器”类,然后在必要时将指向结构的指针传递给非托管代码。 我看到的潜在问题是钉扎有其自身的性能影响。
2)创建一个等价的类,当需要struct时,其字段被复制到struct。 但是复制需要花费很多时间,而且在我看来首先要通过引用来打败它。
编辑:
正如下面提到的几次,我当然可以只测量每种方法的性能。 我会这样做并发布结果。 但是,我仍然有兴趣从知识的角度看待人们的答案和推理。
我做了一些非常非正式的分析,结果表明,对于我的特定应用程序,通过引用传递可以获得适度的性能提升。 对于按值,我每秒大约有10,050,000个呼叫,而对于按引用,我每秒大约有11,200,000个呼叫。
你的旅费可能会改变。
在你询问是否应该通过引用传递结构之前,你应该问问自己为什么你首先得到了如此庞大的结构。 它真的需要是一个结构吗? 如果你需要在某个时候使用一个结构来进行P / Invoke,那么是否值得拥有一个结构,然后是其他地方的等价类?
一个大的结构非常非常不寻常……
有关此更多指导,请参阅“ 在类和结构之间进行选择 ”中的“开发类库的设计指南”部分。
获得这个问题答案的唯一方法是对两者进行编码并测量性能。
你提到了非托管/托管互操作。 我的经验是,互操作需要花费相当长的时间。 您可以尝试更改以下代码:
void ManagedMethod(MyStruct[] items) { foreach (var item in items) { unmanagedHandle.ProcessOne(item); } }
至:
void ManagedMethod(MyStruct[] items) { unmanagedHandle.ProcessMany(items, items.Count); }
这种技术在类似的情况下帮助了我,但只有测量结果会告诉你它是否适用于你的情况。
为什么不直接使用类,并将您的类传递给P / Invoke函数?
使用类将在托管代码中很好地传递,并且与通过引用P / Invoke函数传递结构相同。
例如
// 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 );
- 如何使用DataContractSerializer反序列化XML
- 如何获取C#WebBrowser控件来显示jpeg文件(原始)?
- InvalidArgument =值’0’对’SelectedIndex’无效
- 在Windows Phone上将base64字符串转换为C#中的图像
- 双击C#中的Windows窗体
- Winforms ListView选择图?
- Microsoft Enterprise Library类型加载exception无法加载Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer
- 缩短一行像素数
- 在字符串属性的xml序列化中缩进文本?