Hash-consing besteht darin, nur eine Kopie eines gegebenen Objekts im Speicher zu behalten; Das heißt, wenn zwei Objekte semantisch gleich sind (gleicher Inhalt), dann sollten sie physikalisch gleich sein (gleicher Ort im Speicher). Die Technik wird normalerweise implementiert, indem ein globaler Hash-Satz beibehalten und neue Objekte nur dann erzeugt werden, wenn sie einem Objekt im Hash-Satz nicht gleich sind.Hash-Consing in F # und schwache Hash-Tabellen in .net
Eine zusätzliche Anforderung besteht darin, dass Objekte in der Hash-Tabelle erfassbar sein sollten, wenn sie nur von der Hash-Tabelle referenziert werden; ansonsten sollte die Hash-Tabelle schwache Referenzen enthalten.
Das Problem wird weiterhin durch die Notwendigkeit, konstante Zeit haben, daher flach, Hashing und Gleichheit Tests; Somit haben Objekte einen eindeutigen Bezeichner, der erhöht wird, wenn ein neues Objekt zur Tabelle hinzugefügt wird.
Ich habe eine funktionierende Implementierung, die System.Collections.Generic.Dictionary<key, node>
verwendet, wobei key
ein Tupel ist, das eine flache Zusammenfassung des Knotens gibt Das einzige Problem ist, dass die Dictionary
starke Referenzen zu den Knoten hält!
Ich könnte eine Dictionary
zu WeakReference
's verwenden, aber dies würde nicht die Schlüssel frei, die zu dangling Referenzen zeigen.
Einige Befürworter mit System.Runtime.CompilerServices.ConditionalWeakTable
aber diese Klasse scheint das Gegenteil zu tun: Es befreit den Wert, wenn der Schlüssel gesammelt wird, während ich den Schlüssel freigeben muss, wenn der Wert gesammelt wird.
Man könnte versuchen System.Runtime.CompilerServices.ConditionalWeakTable<node, node>
verwenden, aber ich würde ... custom Hashing und Gleichheitstests benötigt und ConditionalWeakTable
dokumentiert nicht die GetHashCode()
virtuelle Methode zu verwenden, anstatt die Standard-Hash-Funktion verwendet wird.
Also meine Frage: gibt es ein Äquivalent von Dictionary
, die schwache Referenzen auf Werte halten und die Schlüssel freigeben würde, wenn die Referenzen baumeln?
Müssen Sie den Schlüssel sofort freigeben, wenn der Wert erfasst wird? Oder könnten Sie die Anforderung lockern und den Schlüssel erst zu einem späteren Zeitpunkt freigeben? –
Ich brauche sie nicht, um sofort befreit zu werden - es ist nur so, dass ich nicht möchte, dass sie sich anhäufen und nutzlos viel Speicher verbrauchen.Ich habe darüber nachgedacht, einen anderen Thread auszuführen, um regelmäßig Keys mit unpassenden Referenzen zu löschen, aber das scheint kompliziert und anfällig für Parallelitätsfehler. –
Für was es wert ist, habe ich auch eine OCaml-Implementierung mit der Hash-Tabelle aus dem "Weak" -Modul und eine Java-Implementierung usiong 'WeakHashMap'. –