【发布时间】:2013-03-15 01:38:00
【问题描述】:
Hash-consing 包括在内存中只保留给定对象的一个副本;也就是说,如果两个对象在语义上是相等的(相同的内容),那么它们应该在物理上是相等的(在内存中的相同位置)。该技术通常通过保持一个全局哈希集并仅当它们不等于哈希集中的对象时才创建新对象来实现。
另外一个要求是,如果哈希表中的对象没有被哈希表以外的任何东西引用,则它们应该是可收集的;否则,哈希表应该包含弱引用。
由于需要有恒定的时间,因此问题更加复杂,因此需要进行浅层、散列和相等测试;因此,对象具有唯一标识符,当新对象添加到表中时,该标识符会递增。
我有一个使用System.Collections.Generic.Dictionary<key, node> 的工作实现,其中key 是一个元组,给出了节点的浅层摘要(适用于默认散列和相等测试),node 是对象。唯一的问题是 Dictionary 保持对节点的强引用!
我可以使用Dictionary 到WeakReference,但这不会释放指向悬空引用的键。
有些人提倡使用System.Runtime.CompilerServices.ConditionalWeakTable,但这个类似乎做了相反的事情:它在收集键时释放值,而我需要在收集值时释放键。
可以尝试使用System.Runtime.CompilerServices.ConditionalWeakTable<node, node>,但我需要自定义散列和相等性测试...并且ConditionalWeakTable 被记录不使用GetHashCode() 虚拟方法,而不是使用默认散列功能。
因此我的问题是:是否有一些等价的 Dictionary 可以保留对值的弱引用并在引用悬空时释放键?
【问题讨论】:
-
取值后是否需要立即释放key?或者您可以放宽要求,并在稍后的某个时间点释放密钥?
-
我不需要立即释放它们——只是我不希望它们堆积并无用地消耗大量内存。我考虑过运行另一个线程来定期杀死带有悬空引用的键,但这似乎很复杂并且容易出现并发错误。
-
您能否在 F# 中使用 OCaml 代码作为参考实现来实现弱哈希表? IIRC 弱哈希集使用弱数组,可以使用 Array
来实现。 -
另外,
DependentHandle可能会有所帮助:Ephemerons in .NET and C#