【问题标题】:NET] Why is struct better with being less than 16 bytesNET] 为什么小于 16 字节的结构更好
【发布时间】:2011-01-27 03:10:25
【问题描述】:

我正在研究 .NET 结构 - 有些书建议在实例大小小于 16 字节时创建结构。

为什么会这样?

【问题讨论】:

标签: .net


【解决方案1】:

这是因为 16 字节是编译器开始将结构复制为内存块而不是使用一两个简单移动指令的阈值。

当结构较小时,编译器会优化结构的复制。例如 8 个字节的结构可以复制为单个 64 位值。一个 16 字节的结构可以被复制为一个或两个奇异值(取决于处理器架构)。当结构体大于 16 字节时,编译器不再尝试优化移动,回退是调用复制一块内存的方法。

(注意:16字节的阈值可能因编译器版本而异,似乎它实际上试图在较新的版本中优化超过该点,但优化后的代码仍然会是很多移动指令,与复制对仍然是单个移动操作的对象的引用。)

编辑:
这是我在 64 位系统上复制结构十亿次的测试结果:

struct 4    : 272 ms.
struct 8    : 235 ms.
struct 16   : 317 ms.
struct 32   : 625 ms.
struct 64   : 1280 ms.
struct 128  : 4659 ms.
struct 256  : 8020 ms.

如您所见,16 字节以下的时间不是线性的,虽然 16 字节是 4 字节的四倍,但它不会花费四倍的时间。超过 16 个字节的时间是线性的,因此将大小加倍是时间的两倍。这就是它开始使用多个动作的地方。超过 64 字节有一个跳跃,当大小翻倍时,时间突然翻了两番。这就是开始使用后备的地方。

【讨论】:

  • 你有测试来衡量复制一个类的引用所需的时间吗?
  • 我上次检查时,x86 将阈值提高到 20 个字节,x64 将其提高到 24。具有 2 次幂值的表不会注意到,但结构需要保持例如一个 GUID 加上一个引用——即使它大于 16 个字节,也可以在 x86 和 x64 上快速复制。
  • 64 字节恰好是您 PC CPU 的缓存行大小。超过该大小的跳跃可能与它有关。
  • “例如 8 个字节的结构可以复制为单个 64 位值” - 这与说“例如 64 位的结构可以复制为单个 64 位值”?
  • @Guffa 我同意您的说法,话虽如此,我不明白,因为如果您正在检查复制的 ms / 字节的比率,您可以看到复制时出现实际间隙一个 128 字节的结构。响应。 68; 29.375; 19.8125; 19.53125; 20; 36.3984375; 31.328125
【解决方案2】:

它不完全是 16 个字节,但是因为结构是按值传递的(每当您将它们提供给方法、分配它们等时都会复制)它们不能太大。如果是这样,通过引用传递内容会更便宜。

4 年后:我回答这个问题时对 .NET 知之甚少(仍然不太了解)。在处理“多于或少于 16 个字节?”时,Guffa 的答案显然更正确,因为在那个大小下,复制一点也不重要。在构建大型结构时,我的答案可能需要牢记。

【讨论】:

  • 64 位指针仍然比 128 位结构便宜。这个答案真的没有多大意义。
  • “64 位指针仍然比 128 位结构便宜”。你为什么这么说?获取指针通常意味着堆分配和垃圾收集,这在 .NET 上是昂贵的。写入指针意味着会产生写入障碍,这在 .NET 上也很昂贵。
  • @slugster:一个 8 字节的引用可以比一个 16 字节的结构更便宜地被复制,但是为了使引用有用,它必须标识堆上的一个对象。创建一个包含 16 字节数据的堆对象并复制一百万次对其的引用可能比复制一百万次 16 字节结构更便宜,但是创建一个 16 字节对象、复制两次引用并放弃它将会是比复制 16 字节结构两次(或者可能,甚至 20 次)要昂贵得多。
猜你喜欢
  • 2010-11-08
  • 2019-02-03
  • 1970-01-01
  • 2013-03-26
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
相关资源
最近更新 更多