C#字典内存管理

C#字典内存管理,c#,data-structures,memory-management,dictionary,C#,Data Structures,Memory Management,Dictionary,我有一个字典,它可能包含超过1000万个唯一键。我正在努力减少这需要的内存量,同时仍然保持字典的功能 我的想法是将字符串的散列存储为一个长字符串,这样可以将应用程序的内存使用量降低到可接受的程度(~1.5 gig到~0.5 gig),但我对我的方法感觉不太好 long longKey= BitConverter.ToInt64(cryptoTransformSHA1.ComputeHash(enc.GetBytes(strKey)), 0); 基本上,这将切掉SHA1散列的末尾,并将其第一块放

我有一个
字典
,它可能包含超过1000万个唯一键。我正在努力减少这需要的内存量,同时仍然保持字典的功能

我的想法是将字符串的散列存储为一个长字符串,这样可以将应用程序的内存使用量降低到可接受的程度(~1.5 gig到~0.5 gig),但我对我的方法感觉不太好

long longKey=
BitConverter.ToInt64(cryptoTransformSHA1.ComputeHash(enc.GetBytes(strKey)), 0);
基本上,这将切掉SHA1散列的末尾,并将其第一块放入一个long中,然后我将其用作键。虽然这是可行的,但至少对于我测试的数据来说,我觉得这不是一个非常可靠的解决方案,因为键冲突的可能性增加了

有没有其他方法可以减少字典的内存占用,或者我上面的方法没有我想象的那么可怕

[编辑]
为了澄清,我需要保持使用字符串查找字典中包含的值的能力。在字典中存储实际字符串需要占用大量内存。我想做的是使用
字典,其中long是字符串哈希函数的结果。

为什么不使用
GetHashCode()
来获取字符串的哈希值呢?

对于我过去使用过的哈希表实现,散列将您带到一个bucket,它通常是具有相同散列的其他对象的链接列表。散列不是唯一的,但它们足以将您的数据分割成非常易于管理的列表(有时只有2或3个长度),然后您可以通过搜索找到实际的项目


好的散列的关键不是它的唯一性,而是它的速度和分布能力。。。您希望它尽可能均匀地分布。

顺便说一句,加密散列/散列函数对字典非常不利。它们又大又慢。通过解决一个问题(大小),您只引入了另一个更严重的问题:函数将不再均匀地分布输入,从而破坏了用于接近无冲突寻址的良好哈希的最重要属性(正如您自己似乎已经注意到的)


/编辑:正如Andrew所指出的,
GetHashCode
是这个问题的解决方案,因为这是它的预期用途。就像在真正的字典里一样,你必须解决冲突。最好的方案之一就是。不幸的是,唯一100%可靠的方法将是实际存储原始值。否则,您将创建一个无限压缩,我们知道这是不可能存在的。

对于1000多万条记录,您是否考虑过使用具有非聚集索引的数据库?对于这类事情,数据库有更多的技巧

根据定义,在任何算法下,哈希都有可能发生冲突,尤其是在高容量情况下。根据具体情况,我会对此非常谨慎


使用字符串可能会占用空间,但它是可靠的。。。如果您使用的是x64,那么它不必太大(尽管它肯定算作“大”;-p)

所以我最近也做了类似的事情,并且出于我的应用程序特有的一系列原因,我没有使用数据库。事实上,我试图停止使用数据库。我发现GetHashCode在3.5中得到了显著改进。一个重要的注意事项是,永远不要持久存储GetHashCode的结果。从来没有。它们不能保证在框架的不同版本之间保持一致

因此,您确实需要对数据进行分析,因为不同的散列函数可能对您的数据起到更好或更坏的作用。你还需要考虑速度。一般来说,加密哈希函数不应该有太多冲突,即使哈希数达到数十亿。对于我需要独特的东西,我通常使用SHA1管理。一般来说,CryptoAPI的性能很差,即使底层哈希函数的性能很好

对于64位哈希,我目前使用Lookup3和FNV1,它们都是32位哈希。要发生碰撞,两者都需要碰撞,这在数学上是不可能的,而且我还没有见过超过1亿个哈希发生碰撞。您可以在web上找到公开的代码

还是自己分析吧。对我有用的东西可能对你不起作用。实际上,在我的办公室内,不同需求的不同应用程序实际上使用不同的哈希函数或哈希函数的组合


我会避免使用任何未经验证的哈希函数。hash函数的数量和那些认为应该编写它们的人一样多。做你的研究和测试

去拿SQLite吧。你不太可能战胜它,即使你做到了,也可能不值得花费时间/精力/复杂性


SQLite。

我怀疑使用64位哈希时发生冲突的可能性是否现实。我想也是这样,但只是将字节“切碎”一半似乎有点不确定。我开始意识到这个问题可能真的很糟糕。请随时通知我们,我对您的最终解决方案非常感兴趣。字符串首先有多大?我不知道GetHashCode不可靠-更多信息?Diadistis:你为什么这么说?这就是函数的作用所在!根据我的理解,字符串上的GetHashCode是可靠的(确定性的),但不是唯一的。字典不是这样用的。它不允许密钥冲突。您必须使用不同的数据结构并处理冲突,您需要同时存储散列键和实键——除非您还知道要查找的值。这不会节省任何内存。哈希键可能是全等的,但不是等价的。他正在使用散列字符串作为键。这就是为什么他们不能使用string.GetHashCode()作为键的原因,因为给定了样本大小的重复。