【问题标题】:Why is a 1 character .NET string 32 bytes in x64?为什么 x64 中 1 个字符的 .NET 字符串是 32 个字节?
【发布时间】:2011-12-04 17:47:33
【问题描述】:

我一直试图找出 .NET 4 x64 中字符串的开销。这就是我目前所得到的。

  • x64 的 16 字节对象标头
  • 4 个字节的 stringLength 字段(arrayLength 在 .NET 4 中消失了)
  • (length + 1) * 2 字节的字符串内容(UTF-16,以空结尾)

因此,您希望 1 个字符的字符串为 16 + 4 + 4 = 24 字节。它可以被 8 整除,因此不需要任何填充。

但是当我查看 WinDbg 中的大小时,我发现它们占用了 32 字节。当我!dumpobject 他们时,他们说他们的大小是 28 字节,我认为这是四舍五入到 32。这是怎么回事?是否正在发生另一轮内存对齐?

【问题讨论】:

  • 试着把字符串加长... 2、3 和 4 个字符需要多少内存?
  • @xanatos:每个字符多出 2 个字节。
  • 起始字符可能对齐?
  • @leppie 所以 28 = 1 个字符、30 = 2 个字符、32 = 3 个字符和 34 = 4 个字符?
  • @xanatos:再次阅读问题。 1 个字符是 32 :)

标签: .net string memory .net-4.0


【解决方案1】:

怀疑第一个字符在 x64 上的 8 字节边界上对齐,因此当作为指向非托管代码的指针传递时,它是一个正确对齐的指针。你的数字肯定适合最近the ones I got measuring string size,导致公式:

32 bit: 14 + length * 2 (rounded up to 4 bytes) 
64 bit: 26 + length * 2 (rounded up to 8 bytes)

所以在 64 位 CLR 中,即使是长度为 0 的字符串,据我估计也需要 32 个字节。

【讨论】:

  • 看起来确实可能是第一个字符的 8 字节对齐加上整个对象的 8 字节填充。我想一个后续问题是像这样对齐的字段。我四处寻找,这似乎不是一般规则:例如,当您在一个类中混合 long 和 int 时,它们很乐意紧密地打包在一起,而不是在 8 字节边界上对齐。互联网搜索一无所获。 :(
  • 字符串是使用原生大小的整数复制的,所以我想它们至少部分对齐,这样可以更有效地复制它们。
【解决方案2】:

四舍五入到段落(16 字节)边界以优化英特尔处理器上的高速缓存行填充?

【讨论】:

  • 我不认为是这样,因为我在 WinDbg 中也看到了一堆 40 字节的字符串。
【解决方案3】:

据我了解,您不能依赖 .NET 在实现方面的任何东西 - 仅仅因为它在您的机器上是 x 字节,并不意味着它在其他机器/.NET 版本上是 x 字节。也就是说,在知道 .NET 类的内部结构布局的情况下在代码中做任何事情都是危险的。

【讨论】:

  • 没错,但这个特殊的问题似乎只是出于好奇。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
  • 2018-09-07
  • 2011-09-13
  • 1970-01-01
  • 2017-10-07
  • 2011-10-31
相关资源
最近更新 更多