压实一个WeakReference的词典词典、压实、WeakReference

2023-09-08 09:03:07 作者:感性不性感

我有一个类的富的带属性的编号的。我的目标是,有没有两个实例的富的具有相同的编号的在同一时间。

I've got a class Foo with a property Id. My goal is that there are no two instances of Foo with the same Id at the same time.

所以,我创建了一个工厂方法的 CreateFoo 的,它使用一个缓存,以便返回相同的实例相同的编号的。

So I created a factory method CreateFoo which uses a cache in order to return the same instance for the same Id.

static Foo CreateFoo(int id) {
    Foo foo;
    if (!cache.TryGetValue(id, out foo)) {
        foo = new Foo(id);
        foo.Initialize(...);
        cache.Put(id, foo);
    }
    return foo;
}

高速缓存被实现为一个字典&所述; TKEY的,WeakReference的>中基于的 @JaredPar 的Building一个WeakReference的哈希表:

class WeakDictionary<TKey, TValue> where TValue : class {
    private readonly Dictionary<TKey, WeakReference> items;
    public WeakDictionary() {
        this.items = new Dictionary<TKey, WeakReference>();
    }
    public void Put(TKey key, TValue value) {
        this.items[key] = new WeakReference(value);
    }
    public bool TryGetValue(TKey key, out TValue value) {
        WeakReference weakRef;
        if (!this.items.TryGetValue(key, out weakRef)) {
            value = null;
            return false;
        } else {
            value = (TValue)weakRef.Target;
            return (value != null);
        }
    }
}

的问题是,在WeakReferences保留在字典他们的目标已被被垃圾收集后。这意味着需要一些策略如何手动垃圾回收死在WeakReferences,通过的 @Pascal Cuoq 的在的解释是什么恰好GC WeakReference.Target的后WeakReference的。

The problem is that the WeakReferences remain in the dictionary after their targets have been garbage collected. This implies the need for some strategy how to manually "garbage collect" dead WeakReferences, as explained by @Pascal Cuoq in What happens to a WeakReference after GC of WeakReference.Target.

我的问题是:?什么是压缩一个WeakReference的意思是最好的策略

这是我看到的选项有:

不要从字典中删除在WeakReferences。国际海事组织这是不好的,因为缓存采用的是我的应用程序的完整生命周期,而在WeakReferences死了很多的会随时间积累。

走在整个字典上每个的把和 TryGetValue 的,并去除死在WeakReferences。这违背有点意思的目的,因为这两个操作成为的 O(N)的。

Walk the entire dictionary on each Put and TryGetValue, and remove dead WeakReferences. This defeats somewhat the purpose of a dictionary because both operations become O(n).

定期遍历整个字典在后台线程。什么将是一个很好的时间,因为我不知道的使用模式的 CreateFoo 的?

Walk the entire dictionary periodically in a background thread. What would be a good interval, given that I don't know the usage pattern of CreateFoo?

每个附加插入KeyValuePair一个双端链表。每次调用的把和 TryGetValue 的检查列表的头部。如果WeakReference的是活的,移动对添加到列表的末尾。如果是死了,去掉对从列表和从字典中的WeakReference。

Append each inserted KeyValuePair to a double-ended linked list. Each call to Put and TryGetValue examines the head of the list. If the WeakReference is alive, move the pair to the end of the list. If it is dead, remove the pair from the list and the WeakReference from the Dictionary.

实施条件是,当一个桶满,死在WeakReferences首先从桶里继续像往常一样没有带走的微小差别的自定义哈希表。

Implement a custom hash table with the minor difference that, when a bucket is full, dead WeakReferences are first removed from the bucket before proceeding as usual.

还有其他策略?

最好的策略可能是一个算法的分期时间复杂度。有没有这样的战略存在吗?

The best strategy is probably an algorithm with amortized time complexity. Does such a strategy exist?

推荐答案

您选择3(线程)已作出必要对所有的看跌/ TryGetvalue行动同步的大的缺点。如果你使用,你的时间是不是以毫秒为单位,但每N TryGet行动。

Your Option 3 (a Thread) has the big disadvantage of making synchronization necessary on all Put/TryGetvalue actions. If you do use this, your interval is not in milliseconds but every N TryGet actions.

选项2,扫描词典,会招致严重的开销。可以通过只扫描1在1000动作和/或通过观看多久的GC已经用完提高

Option 2, scanning the Dictionary, would incur a serious overhead. You can improve by only scanning 1 in 1000 actions and/or by watching how often the GC has run.

不过,我会认真考虑的选项1:什么也不做。您可能必须死条目的很多,但另一方面,他们是pretty的小(和得到回收)。可能不是一个服务器应用程序,但对于客户端应用程序,我会试图让多少项(k字节)的时速,我们正在谈论的措施的选项。

But i would seriously consider option 1: Do nothing. You may have "a lot" of dead entries but on the other hand they are pretty small (and get recycled). Probably not an option for a Server App but for a Client application I would try to get a measure on how many entries (kByte) per hour we are talking about.

请问这样的[N摊销]策略   存在吗?

Does such a[n amortized] strategy exist?

我想没有。你的问题是GC的微缩版。你将不得不在一段时间扫描整个事情一次。因此,只有选择2)和3)提供了一个真正的解决方案。和它们都是昂贵的,但它们可以是(重)优化的一些启发式。选项​​2)将仍然给你的偶尔的最坏情况虽然。

I would guess no. Your problem is a miniature version of the GC. You will have to scan the whole thing once in a while. So only options 2) and 3) provide a real solution. And they are both expensive but they can be (heavily) optimized with some heuristics. Option 2) would still give you the occasional worst-case though.

 
精彩推荐
图片推荐