c# - ¿Por qué.NET no tiene SoftReference ni WeakReference, como Java?
weak-references soft-references (9)
Creo que la razón fundamental por la que NET no tiene referencias suaves es porque puede confiar en un sistema operativo con memoria virtual. Un proceso de Java debe especificar su memoria máxima de sistema operativo (por ejemplo, con -Xmx128M
), y nunca se necesita más memoria de sistema operativo que eso. Mientras que un proceso NET sigue teniendo la memoria del sistema operativo que necesita, que el sistema operativo proporciona con memoria virtual respaldada por disco cuando se agota la memoria RAM. Si NET permitía referencias suaves, el tiempo de ejecución de NET no sabría cuándo liberarlas a menos que se asomara profundamente en el sistema operativo para ver si su memoria estaba realmente paginada en el disco (una desagradable dependencia de OS / CLR), o si solicitó el tiempo de ejecución para especifique una huella de memoria de proceso máxima (por ejemplo, un equivalente de -Xmx
). Supongo que Microsoft no quiere agregar -Xmx
a NET porque creen que el sistema operativo debería decidir cuánta RAM obtiene cada proceso (eligiendo qué páginas de memoria virtual se almacenarán en la RAM o en el disco) y no el proceso en sí.
Me encanta WeakReference''s. Pero desearía que hubiera una manera de decirle al CLR cuánto (por ejemplo, en una escala del 1 al 5) qué tan débil considera que es la referencia. Eso sería genial.
Java tiene SoftReference, WeakReference y creo que también un tercer tipo llamado "referencia fantasma". Son 3 niveles allí donde el GC tiene un algoritmo de comportamiento diferente para decidir si ese objeto recibe el corte.
Estoy pensando en subclasificar la WeakReference de .NET (afortunada y levemente no está sellada) para hacer una pseudo-SoftReference basada en un temporizador de vencimiento o algo así.
¿Buscando la opción ''trackResurrection'' pasada al constructor quizás?
La clase GC también ofrece algo de ayuda.
Mi suposición de por qué esto ya no está allí sería la simplicidad. La mayoría de la gente, creo, llamaría una virtud que solo hay un tipo de referencia, no cuatro.
Tal vez debería haber una propiedad en la que pueda especificar qué generación es el objeto> = antes de que se recopile. Entonces, si especifica 1, entonces es la referencia más débil posible. Pero si especifica 3, necesitaría sobrevivir al menos 3 colecciones anteriores antes de que se pueda considerar para la recopilación.
Pensé que la bandera de resolución de seguimiento no era buena para esto porque para ese momento el objeto ya había sido finalizado. Aunque puede estar equivocado ...
(PD: Soy el OP, acabo de firmar. PITA dice que no hereda su historial de cuentas "no registradas").
Tener una WeakReference con diferentes niveles de debilidad (prioridad) suena bien, pero también puede hacer que el trabajo del GC sea más difícil, no más fácil. (No tengo ni idea de las partes internas de GC, pero) Asumiría que hay algún tipo de estadísticas de acceso adicionales que se guardan para los objetos WeakReference para que el GC pueda limpiarlos de manera eficiente (por ejemplo, podría deshacerse de los elementos menos usados) primero).
Lo más probable es que la complejidad agregada no haga que nada sea más eficiente porque la forma más eficiente es deshacerse primero de las WeakReferences que se utilizan con poca frecuencia. Si pudieras asignar una prioridad, ¿cómo lo harías? Esto huele a una optimización prematura: el programador en realidad no sabe la mayor parte del tiempo y está adivinando; el resultado es un ciclo de recolección de GC más lento que probablemente recupera los objetos equivocados.
Sin embargo, plantea la pregunta de que si te preocupa que se reclame el objeto WeakReference.Target, ¿es realmente un buen uso de WeakReference?
Es como un caché. Introduces cosas en el caché y le pides al caché que se vuelva obsoleto después de x minutos, pero la mayoría de los cachés nunca garantizan mantenerlo en absoluto. Simplemente garantiza que, si lo hace, expirará de acuerdo con la política solicitada.
No olvide que también tiene sus referencias estándar (las que usa a diario). Esto te da un nivel más.
Las WeakReferences deben usarse cuando no te importa realmente si el objeto desaparece, mientras que las SoftReferences solo deben usarse cuando uses una referencia normal, pero prefieres que se borre tu objeto para que te quedes sin memoria. No estoy seguro de los detalles, pero sospecho que el GC normalmente rastrea a través de SoftReferences pero no de WeakReferences al determinar qué objetos están activos, pero cuando se ejecuta bajo en memoria también se saltará las referencias suaves.
Mi suposición es que los diseñadores de .Net sintieron que la diferencia era confusa para la mayoría de las personas o que las SoftReferences agregaban más complejidad de la que realmente querían y decidieron dejarlas fuera.
Como nota al margen, AFAIK PhantomReferences están diseñados principalmente para uso interno por la máquina virtual y no están destinados al uso real del cliente.
No sé por qué .NET no tiene Softreferences. PERO en Java Softreferences se sobreutiliza en mi humilde opinión. La razón es que, al menos en un servidor de aplicaciones, le gustaría poder influir por aplicación durante cuánto tiempo durará su Softreferenzen. Eso actualmente no es posible en Java.
Las referencias suaves de Java se utilizan en la creación de memorias caché sensibles a la memoria (no sirven para otro propósito).
A partir de .NET 4, .NET tiene una clase System.Runtime.Caching.MemoryCache que probablemente satisfará esas necesidades.
¿Tal vez la clase ASP.NET Cache (System.Web.Caching.Cache) podría ayudar a lograr lo que quieres? Quita objetos automáticamente si la memoria baja:
Aquí hay un artículo que muestra cómo usar la clase Cache en una aplicación de formularios de Windows.
citado de: ¿ Equivalente a SoftReference en .net?