Сжатие словаря слабых ссылок
У меня есть классFoo с собственностьюЯ бы, Моя цель состоит в том, чтобы не было двух случаевFoo с тем жеЯ бы в то же время.
Итак, я создал фабричный методCreateFoo который использует кэш для того, чтобы вернуть тот же экземпляр для того жеЯ бы.
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«sСоздание хеш-таблицы 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, как объяснено@ Паскаль Куок вЧто происходит с WeakReference после GC WeakReference.Target.
Мой вопрос:Какова лучшая стратегия для сжатия словаря WeakReference?
Варианты, которые я вижу:
Не удаляйте WeakReferences из словаря. ИМО это плохо, потому что кеш используется в течение всего времени жизни моего приложения, имного из мертвых WeakReferences будут накапливаться с течением времени.
Пройдите весь словарь по каждомуСтавить а такжеTryGetValueи удалите мертвые WeakReferences. Это несколько противоречит цели словаря, потому что обе операции становятсяНа).
Периодически проходите весь словарь в фоновом потоке. Что было бы хорошим интервалом, учитывая, что я не знаю модель использованияCreateFoo?
Добавьте каждый вставленный KeyValuePair в двусторонний связанный список. Каждый звонокСтавить а такжеTryGetValue осматривает голову списка. Если WeakReference жив, переместите пару в конец списка. Если он мертв, удалите пару из списка и WeakReference из словаря.
Реализуйте пользовательскую хеш-таблицу с небольшим отличием, что, когда корзина заполнена, мертвые WeakReferences сначала удаляются из корзины, а затем продолжают обычную работу.
Есть ли другие стратегии?
Лучшая стратегия - это алгоритм с амортизированной временной сложностью. Существует ли такая стратегия?