Hash-consing состоит в сохранении в памяти только одной копии данного объекта; то есть, если два объекта семантически равны (одно и то же содержимое), то они должны быть физически равными (одно и то же местоположение в памяти). Этот метод обычно реализуется путем сохранения глобального набора хэшей и создания новых объектов только в том случае, если они не равны объекту в хэш-наборе.Хэш-consing в F # и слабые хэш-таблицы в .net
Дополнительным требованием является то, что объекты в хэш-таблице должны собираться, если на них не ссылаются ни на что иное, кроме хеш-таблицы; в противном случае хеш-таблица должна содержать слабые ссылки.
Проблема, кроме того, осложняется необходимостью иметь постоянное время, таким образом, неглубокие, хэширование и тесты на равенство; таким образом, объекты имеют уникальный идентификатор, который увеличивается при добавлении нового объекта в таблицу.
У меня есть рабочая реализация, которая использует System.Collections.Generic.Dictionary<key, node>
, где key
является кортежем, дающим мелкую сводку узла (подходит для теста хэширования и равенства по умолчанию) и node
является объектом. Единственная проблема заключается в том, что Dictionary
сохраняет сильные ссылки на узлы!
Я мог бы использовать Dictionary
до WeakReference
, но это не освободит ключи, указывающие на оборванные ссылки.
Некоторые защитники используют System.Runtime.CompilerServices.ConditionalWeakTable
, но этот класс, похоже, делает обратное: он освобождает значение при сборке ключа, тогда как мне нужно освободить ключ при сборке значения.
Можно попробовать использовать System.Runtime.CompilerServices.ConditionalWeakTable<node, node>
, но я должен был бы заказ хэширования и равенства тестов ... и ConditionalWeakTable
документирована не использовать виртуальный метод GetHashCode()
, вместо того, чтобы с помощью функции хэширования по умолчанию.
Таким образом, мой вопрос: есть ли какой-то эквивалент Dictionary
, который будет поддерживать слабые ссылки на значения и освобождать ключи, когда ссылки становятся свисающими?
Вам нужно освободить ключ сразу после сбора значения? Или вы могли бы расслабиться и просто освободить ключ в какой-то более поздний момент? –
Мне не нужно, чтобы их немедленно освободили - просто я не хочу, чтобы они накапливались и бесполезно потребляли много памяти.Я думал о запуске другого потока, чтобы периодически убивать ключи с оборванными ссылками, но это кажется сложным и подверженным ошибкам параллелизма. –
Для чего это стоит, у меня также есть реализация OCaml с использованием хеш-таблицы из модуля 'Weak' и реализация Java usiong' WeakHashMap'. –