C#中字典的内存使用情况

13

我有一些代码,我向其中添加了嵌套字典,格式如下:

Dictionary<string, Dictionary<string, Dictionary<string, float>>>

在这样做之后,我注意到我的应用程序的内存使用量显著增加。这些字典是以经常重复的字符串为键的,并且有许多这样的字典,数量达到数万个。

为了解决这个问题,我假设重复的字符串占用了大量的内存。我的解决方案是将字符串哈希化并使用整数代替(我会保留一份彩虹表的副本以便在必要时还原哈希)。

Dictionary<int, Dictionary<int, Dictionary<int, float>>>

所以我使用了一个内存分析器来查看能够获得什么样的大小减小。令我震惊的是,实际上我发现字符串存储的大小(包括正常和全面)都更小了。

这对我来说并不直观。即使编译器足够聪明,只存储字符串的一个副本并使用引用,我认为该引用将是指针,其大小是int的两倍。我也没有使用任何String.Intern方法,因此我不知道如何完成这项任务(同时,这里是否适合使用String.Intern方法?)

我非常困惑正在发生什么,感谢任何帮助。


3
引擎底层没有进行特别处理。要么您的字符串缓存策略未能去除大量冗余,要么存在错误。您需要发布代码。 - usr
3
也许你可以使用 Dictionary<Tuple<string, string, string>> 来消除嵌套。Dictionary 不是一个小型类型。使用结构元组。 - usr
2
相比之前,"shot up SIGNIFICANTLY."(急剧上升)。(请注意,除非您澄清它的方式,否则http://stackoverflow.com/questions/20430157/memory-usage-of-dictionary-in-c-sharp可以用作您的问题的重复目标) - Alexei Levenkov
1
使用字典的字典通常只是表明您应该创建一个新类型。总共有多少个字典? - Anders Forsgren
那么你期望存储在字典中的信息是如何存储的呢?仅仅将新对象添加到已实例化的类中会增加额外的内存...但这对我来说并不像是真正的比较,无法称之为“激增”。 - Alexei Levenkov
显示剩余8条评论
1个回答

23
如果你的键和值是对象,每个字典元素会有大约20个字节的开销,加上每个字典本身的几个字节。这还不包括键和值本身所占用的空间。如果你的键和值是值类型,则每个字典项的开销为12个字节加上键和值所占用的空间。这是在元素数量等于内部字典容量的情况下。但通常容量比元素多,因此有浪费的空间。
如果你有很多只有少量元素的字典,浪费的空间相对比例会更高,而不是一个有许多元素的字典。如果我按照你的评论来看,你的8个元素的字典将具有11个容量,2个元素的字典将具有3个容量,而10个元素的字典将具有11个容量。
如果我理解你的嵌套计数,那么单个顶层字典将表示184个字典元素。但如果我们计算未使用的容量,它的空间消耗接近200。每个顶级字典将消耗4000字节,你有多少个呢?你说有成千上万个字典在成千上万个对象中。每10000个字典将消耗约38 MB的字典开销。加上存储在字典中的对象。
如果你尝试通过管理哈希码来缩小它的大小,可能的解释是你的键没有太多重复引用。用int键替换对象引用键不会改变字典开销数量,并且你需要添加存储新哈希代码集合的空间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接