【问题标题】:Why are my .NET strings so large in memory?为什么我的 .NET 字符串在内存中这么大?
【发布时间】:2019-05-31 15:17:30
【问题描述】:

如果我跑步

string myString = "*.txt";
Print("sizeof(char): " + sizeof(char) + " bytes");
Print("myString.Length * sizeof(char): " + (myString.Length * sizeof(char)) + " bytes");

它会打印出来

sizeof(char): 2 个字节

myString.Length * sizeof(char): 10 字节

但是,如果我将第一个答案中的代码运行到this question

myString = "*.txt"
long size = 0;
using (Stream s = new MemoryStream())
{
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(s, myString);
    size = s.Length;
}
Print("myString Serialized Size: " + size + " bytes");

我明白了

myString 序列化大小:29 字节

以下哪一项更准确地表示我的字符串在内存中占用了多少空间?

【问题讨论】:

  • 您为什么不阅读答案中的cmets? “这会放更多。它添加了 DLL 名称和版本,......这不是计算对象大小的方法。”
  • 两者都没有告诉您在内存中保存字符串数据实际需要多少内存。后者序列化一个字符串对象并告诉您序列化数据的大小(包括对象元数据,例如对象类型)。前者以字节为单位告诉您文本数据的长度,但这并不是字符串的全部信息。取第一个结果并添加 4...8 字节以获取额外的字符串长度信息(然后将结果四舍五入到 4 或 8 的下一个倍数,以考虑由于内存对齐可能导致的“浪费”)。这应该是一个不错的估计...

标签: c# performance memory memory-management stream


【解决方案1】:

询问字符串的大小(字节)很复杂;

  • 在内部,它将是 UTF-16,因此:两倍的字符(假设它没有创建过大,这是可能的
    • string 对象本身具有字符串长度要考虑的对象开销,还有“填充”等
  • 如果您在讨论普通二进制编码中的大小,那么您需要知道Encoding 您在讨论什么; ASCII、UTF-8、UTF-16 等 - 加上您需要知道是否包含 BOM
  • 你不会做的一件事就是通过BinaryFormatter 运行它; BinaryFormatter 是一个通用的序列化器,包括类型元数据、字段名等;一般来说,你应该几乎从不使用BinaryFormatter ... 任何东西 :)

所以:你得到一个意想不到的答案的原因是你问错了问题。对于“内存中”的讨论,你真的是在第一个子弹之后。很难给出准确的答案,因为对象开销的大小取决于您的目标平台。

【讨论】:

  • 如果我知道我的目标平台是 Windows,是否有可以用来查找开销的函数?因为我可以编写一个实用方法,该方法根据目标平台采取不同的行动,并且对于每个主要平台都有不同的情况。或者更好的是,是否有一个函数可以找到实际上不在内存中的所有内容的大小,并且可以从 BinaryFormatter 给出的估计值中减去它?
  • @user430481 这不仅仅是 Windows。它是 CPU。它是 .NET 版本。并且停止考虑 BinaryFormatter - 它与您要查找的信息无关。但基本上,“不是真的,每个字符大约 2 个字节加上 4 个字节加上一点”。
猜你喜欢
  • 1970-01-01
  • 2011-02-14
  • 2019-01-09
  • 1970-01-01
  • 1970-01-01
  • 2012-06-30
  • 2014-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多