【问题标题】:Why is KeyValuePair<int, long> 16 bytes?为什么 KeyValuePair<int, long> 是 16 个字节?
【发布时间】:2016-02-02 12:30:19
【问题描述】:
KeyValuePair<int, int>:    8 bytes
KeyValuePair<long, long>: 16 bytes
KeyValuePair<long, int>:  16 bytes (!!)
KeyValuePair<int, long>:  16 bytes (!!)

我希望后两对只需要 8 (long) + 4 (int) = 12 个字节。为什么要占用 16 个?

大小是使用通过 ILGenerator 发出的动态 SizeOf 确定的,如下所述:Size of generic structure

【问题讨论】:

标签: c# struct sizeof keyvaluepair


【解决方案1】:

这是由于data structure Alignment。引用维基百科的文章:

数据对齐意味着将数据放置在等于字大小的某个倍数的内存地址,由于 CPU 处理内存的方式,这提高了系统的性能。为了对齐数据,可能需要在最后一个数据结构的结尾和下一个数据结构的开头之间插入一些无意义的字节,这就是数据结构填充。

由于 int 是 4 个字节,KeyValuePair 为 long,而 int 会导致数据结构不对齐。这将导致性能显着下降。因此,最好在每条记录上“浪费”4 个字节以使数据对齐,从而能够高效地写入和读取。

至于为什么不填充单个整数 - 不要忘记使用结构/类添加填充变量相对容易 - 但对于普通值类型,您没有那个结构/类。我猜测所需的额外工作(在 int 周围添加一个虚拟结构以插入填充)不值得性能提升。

32 位和 64 位操作系统在这里并没有什么区别,它们仍然需要填充和对齐,但是填充量可能会有所不同。

在“过去”中,您经常不得不手动向数据结构添加填充以获得正确的对齐方式,而现在它往往由编译器自动处理。

【讨论】:

  • 我期待着类似的东西。但我也注意到一个普通的 int 没有得到任何填充,即使它不是 8 个字节的倍数。错位是否可以接受?这是一个权衡吗? “我们将拥有如此多的整数,以至于我们希望降低性能以节省内存,但 KeyValuePair 将非常罕见,我们宁愿正确对齐它。”还是我错过了什么?
  • 另外,32 位和 64 位在这里重要吗?尺寸建议不要。
  • @Timo 不,32 位与 64 位无关。
  • 这并不能解释为什么 &lt;int, int&gt; 适合 8 个字节,但不经意间暗示了为什么 &lt;long, int&gt; 的大小不是 12 个字节。您在&lt;int, int&gt;&lt;int, long&gt; 中“有[a] 结构/类”的程度完全相同。当它导致值跨越个单词时,错位是“坏的”;在 1 个字中存储 2 个ints 没有获取惩罚,因此是 8 字节的&lt;int, int&gt;。另一方面,拥有一个 12 字节的结构,可能 导致内存中的 next 相邻值跨越单词。 CIL 似乎通过将结构大小四舍五入到最接近的单词来避免这种情况。
猜你喜欢
  • 2015-07-23
  • 2012-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
  • 2014-05-03
相关资源
最近更新 更多