valor net iset generic framework examples diccionario clave asp .net f# hashmap hashset

iset - Hash-consing en F#y tablas hash débiles en.net



iset c# (1)

Hash-consing consiste en mantener en la memoria solo una copia de un objeto dado; es decir, si dos objetos son semánticamente iguales (el mismo contenido), entonces deberían ser físicamente iguales (la misma ubicación en la memoria). La técnica generalmente se implementa manteniendo un conjunto de hash global y creando nuevos objetos solo si no son iguales a un objeto en el conjunto de hash.

Un requisito adicional es que los objetos en la tabla hash deben ser coleccionables si no están referenciados por nada excepto la tabla hash; dicho de otro modo, la tabla hash debe contener referencias débiles.

El problema se complica, además, por la necesidad de tener pruebas constantes de tiempo, por lo tanto poco profundas, hash e igualdad; por lo tanto, los objetos tienen un identificador único que se incrementa cuando se agrega un nuevo objeto a la tabla.

Tengo una implementación de trabajo que utiliza System.Collections.Generic.Dictionary<key, node> donde key es una tupla que proporciona un resumen superficial del nodo (adecuado para el hashing predeterminado y la prueba de igualdad) y node es el objeto. ¡El único problema es que el Dictionary mantiene fuertes referencias a los nodos!

Podría usar un Dictionary to WeakReference , pero esto no liberaría las claves que apuntan a referencias colgantes.

Algunos recomiendan utilizar System.Runtime.CompilerServices.ConditionalWeakTable pero esta clase parece hacer lo contrario: libera el valor cuando se recopila la clave, mientras que necesito liberar la clave cuando se recopila el valor.

Se podría intentar usar System.Runtime.CompilerServices.ConditionalWeakTable<node, node> pero necesitaría hashing personalizado y pruebas de igualdad ... y se ha documentado que ConditionalWeakTable no usa el método virtual GetHashCode() , sino que utiliza la función de hashing predeterminada.

Por lo tanto, mi pregunta: ¿hay algún equivalente de Dictionary que mantenga las referencias débiles a los valores y libere las claves cuando las referencias se vuelvan peligrosas?


Tiene razón en que CWT no resuelve el problema de la comprobación de hash porque plantea la pregunta: sus claves asumen la igualdad de referencia. Sin embargo, podría valer la pena señalar que CWT no se aferra a claves o valores. Aquí hay una pequeña prueba:

open System.Collections.Generic open System.Runtime.CompilerServices let big () = ref (Array.zeroCreate (1024 * 1024) : byte []) let test1 () = let d = Dictionary(HashIdentity.Reference) for i in 1 .. 10000 do stdout.WriteLine(i) let big = big () d.Add(big, big) d let test2 () = let d = ConditionalWeakTable() for i in 1 .. 10000 do stdout.WriteLine(i) let big = big () d.Add(big, big) d

En mi máquina, test1 queda sin memoria y test2 tiene éxito. Parece que esto solo sucedería si CWT no se aferraba tanto a las claves como a los valores.

Para el control de hash, su mejor apuesta podría ser lo que Artem sugiere en los comentarios. Si esto suena demasiado complicado, también tiene mucho sentido simplemente darle control al usuario, por ejemplo:

let f = MyFactory() // a dictionary with weak reference values hidden inside f.Create(..) : MyObject // MyObject has no constructors of its own f.Cleanup() // explicitly cleans up entries for collected keys

Entonces no necesita introducir hilos, estudiar cómo funcionan los componentes internos de GC o hacer magia. El usuario de la biblioteca puede decidir dónde es apropiado limpiar o simplemente "olvidar" el objeto de fábrica, que recopilaría toda la tabla.