什么时候通过值传递结构更有效率?何时通过引用C#?

loo*_*awa 11 c# performance struct ref

我已经研究了一下,似乎常识认为结构应该在16字节以下,否则它们会导致复制的性能损失.使用C#7和ref返回,完全避免完全避免复制结构变得非常容易.我假设随着结构大小变小,通过ref传递更多的开销只是复制值.

是否有一个经验法则,关于何时通过值传递结构比通过ref更快?哪些因素会影响这个?(结构大小,过程位数等)

更多上下文:我正在开发一款游戏,绝大多数数据都表示为连续的结构数组,以实现最大的缓存友好性.正如您可能想象的那样,在这种情况下传递结构很常见.我知道分析是确定某些内容的性能影响的唯一真正方法.但是,我想了解它背后的理论概念,并希望在编写代码时考虑到这种理解,并仅描述边缘情况.

此外,请注意,我不会询问最佳做法或通过参考传递一切的理智.我知道"最佳实践"和含义,我故意选择不遵循它们.


编辑 - 寻址"重复"标签

按值传递vs传递参考性能C#.net - 此问题讨论通过ref传递引用类型,这与我要求的完全不同.

在.Net中,出于性能原因,我是否应该通过引用传递结构? - 第二个问题涉及到主题,但它是关于结构的特定大小.

要回答Eric Lippert的文章中提出的问题:

你真的需要回答这个问题吗?是的,我愿意.因为它会影响我编写大量代码的方式.

这真的是瓶颈吗?可能不是.但我仍然想知道,因为99%的程序是数据访问模式.在我看来,这类似于选择正确的数据结构.

差异是否相关?它是.通过ref传递大型结构更快.我只是想了解这个的局限性.

你说的这个"更快"是什么?与为同一任务减少CPU工作量相同.

你在看大局吗?是.如前所述,它影响我如何写整个事情.

你为什么甚至问我?因为SO应该是一个Q&A网站.

我知道我可以测量很多不同的组合.这告诉我什么?在我的[.NET版本,进程位,操作系统,CPU]的组合中,X比Y更快.Linux怎么样?Android怎么样?iOS怎么样?我应该对所有可能的硬件/软件组合的所有排列进行基准测试吗?

我认为这不是一个可行的策略.因此,我在这里问一下,对CLR/JIT/ASM/CPU有很多了解的人可以告诉我它是如何工作的,这样我就可以在编写代码时做出明智的决定.

我正在寻找的答案类似于前面提到的结构大小的16字节指南,并解释了原因.

Gid*_*Max 7

通常,通过引用传递应该更快。
当你通过引用传递一个结构体时,你只是传递了一个指向该结构体的指针,它只是一个 32/64 位整数。
当你按值传递一个结构体时,你需要复制整个结构体,然后传递一个指向新副本的指针。
除非结构非常小,例如 int,否则按引用传递会更快。

此外,按值传递会增加对 os 进行内存分配和取消分配的调用次数,这些调用非常耗时,因为 os 必须检查注册表以获取可用空间。

  • 需要更多的经验数据。传递“指针”需要额外的间接,因此(并且取决于实现)除了这个简单的一般性之外还有一些切入点。拐点是什么?在哪里?它如何/为什么在不同环境中有所不同? (4认同)
  • 澄清一下,在这种情况下“非常小”=“小于设备上的指针” (2认同)
  • @Riggy 根据 [Microsoft](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref),“通过引用传递值类型时没有装箱”。 (2认同)
  • 另外,正如@user2864740所说 - 我问的是拐点。1 int 更快,我同意。那么 2 个整数呢?3?4? (2认同)

loo*_*awa 4

我终于找到了答案。断点是System.IntPtr.Size。用 Microsoft 自己在《编写安全高效的 C# 代码》中的话来说:

添加 in 修饰符以通过引用传递参数,并声明您的设计意图通过引用传递参数以避免不必要的复制。您不打算修改用作该参数的对象。

这种做法通常可以提高大于 IntPtr.Size 的只读值类型的性能。对于简单类型(sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal 和 bool 以及 enum 类型),任何潜在的性能提升都是最小的。事实上,对于小于 IntPtr.Size 的类型使用引用传递可能会降低性能。


归档时间:

查看次数:

1188 次

最近记录:

8 年,4 月 前