我有一些代码添加了嵌套字典,格式如下
Dictionary<string, Dictionary<string, Dictionary<string, float>>>
这样做后,我注意到应用程序的内存使用量显着增加。这些词典以经常重复的字符串为键,并且此类词典的数量很多,大约有数十万之多。
为了解决这个问题,我假设重复的字符串消耗了大量的内存。我的解决方案是对字符串进行哈希处理并使用整数(我会保留一份彩虹表的副本,以便在必要时可以反转哈希值)
Dictionary<int, Dictionary<int, Dictionary<int, float>>>
因此,我使用内存分析器来查看可以减少什么样的大小。令我震惊的是,我实际上发现字符串存储的大小实际上更小(正常的和包含的)。
这对我来说没有直观意义。即使编译器足够聪明,只存储字符串的一个副本并使用引用,我也会认为引用将是一个指针,其大小是 int 的两倍。我也没有使用任何String.Intern
方法,所以我不知道这是如何实现的(也是String.Intern
这里的方法正确吗?)
我对幕后发生的事情感到非常困惑,任何帮助将不胜感激
如果您的键和值是对象,则字典的每个元素大约有 20 个字节的开销,再加上每个字典的几个字节。这还不包括键和值本身消耗的空间。如果您将值类型作为键和值,那么它是 12 个字节加上字典中每个项目的键和值占用的空间。这是如果元素数量等于内部字典容量的情况。但通常容量多于元素,因此存在空间浪费。
如果您拥有大量包含少量元素的字典,则浪费的空间通常会比拥有一本包含许多元素的字典更高。如果我按照你的评论,你的字典有 8 个元素,容量为 11,那些有 2 个元素,容量为 3,那些有 10 个元素,容量为 11。
如果我了解您的嵌套计数,那么单个顶级字典将代表 184 个字典元素。但如果我们计算未使用的容量,则空间消耗接近 200。每个顶级字典 200 * 20 = 4000 字节。你有多少个?你说的是数千个对象中的数十个。每 10,000 个将消耗大约 38 MB 的字典开销。添加存储在字典中的对象。
为什么你试图通过管理哈希码来缩小它的一个可能的解释是,如果没有大量对你的密钥的重复引用。用 int 键替换对象引用键不会改变字典开销量,并且您将添加新的哈希码集合的存储。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)