2008-11-27 12 views
13

Me encanta WeakReference's. Pero me gustarí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.¿Por qué .NET no tiene una referencia suave sino también una referencia débil, como Java?

Java tiene SoftReference, WeakReference y creo que también un tercer tipo llamado "referencia ficticia". 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 (afortunadamente y ligeramente bizarramente no está sellada) para hacer una pseudo-SoftReference que se basa en un temporizador de vencimiento o algo así.

+2

Tal vez si explica qué problema está tratando de resolver, quizás obtenga algunas respuestas con buenas soluciones. Por lo general, no es una buena idea trabajar en este nivel de granularidad y es más apropiado algún tipo de caché de espiración, pero todo depende del problema. –

Respuesta

4

Mi suposición de por qué esto no está allí ya sería simple. La mayoría de la gente, creo, llamaría una virtud que solo hay un tipo de referencia, no cuatro.

+3

en realidad, SoftReferences son EXTREMADAMENTE útiles, ya que permiten el almacenamiento en memoria caché sensible a la memoria gc. La mayoría de las personas que realmente entienden para qué sirven, les gustaría tenerlas. En el código de Java utilizo SoftReference MUCH con más frecuencia que WeakReference – user430788

0

¿Busca la opción 'trackResurrection' pasada al constructor tal vez?

La clase GC también ofrece asistencia.

1

Tal vez debería haber una propiedad donde pueda especificar qué Generación que el objeto> = antes de recopilar. 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 ressurection de la pista no era buena para esto porque para ese momento el objeto ya se había finalizado? Que puede estar mal, aunque ...

(PD: Soy el PO, acaba de firmar PITA que no hereda su historial de cuentas "no registradas"..)

4

Tener un WeakReference con diferentes niveles de debilidad (prioridad) suena agradable, 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).

Es muy probable 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.

No obstante, plantea la pregunta de que, si le importa 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.

+0

La diferencia es que usar SoftReference en la memoria caché le permite mantener cosas mientras tenga suficiente memoria pero desechelas si no lo hace. Es una * mucho * solución más eficiente que un tiempo de espera en un caché. – user430788

+0

@ user430788 Creo que echas de menos mi comentario sobre los cachés. Una memoria caché ya podría utilizar WeakReference, pero la caducidad también podría aplicarse a los elementos almacenados en caché. Desde el punto de vista del consumidor de caché, un caché normalmente no garantiza que los elementos permanezcan en el caché.Los desarrolladores ya se quejan del GC, por lo que tal vez el equipo C# sintió que agregar nuevos niveles de referencias débiles (suave, fantasma) no agregaba lo suficiente. Como siempre, http://blogs.msdn.com/b/ericlippert/archive/2003/10/28/how-many-microsoft-employees-does-it-take-to-change-a-lightbulb.aspx de Eric Lippert es una buena lectura para conocer las características de C#. –

+1

Robert, me temo que no me entendiste en absoluto. No, un caché no garantiza que las cosas permanezcan en el caché. Ese es el punto. Pero un caché basado únicamente en el tiempo no hace un buen trabajo al determinar lo que debe y no debe estar en la memoria. Vacía las cosas sin razón. Un caché basado en las necesidades de memoria es mucho mejor para preservar los datos, a menos que realmente sea necesario eliminarlos. Usted PODRÍA implementar un caché LRU usted mismo, pero eso requeriría agregar código de gestión de pseudo memoria a su aplicación. Es mucho más eficiente dejar que el GC que ya administra la memoria administre tu caché. – user430788

0

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.

+0

En HotSpot hay una opción para configurar esto ligeramente: -XX: SoftRefLRUPolicyMSPerMB = xyz. Consulte http://java.sun.com/docs/hotspot/HotSpotFAQ.html#gc_softrefs –

2

No olvide que también tiene sus referencias estándar (las que usa a diario). Esto te da un nivel más.

WeakReferences debe usarse cuando no le importe realmente si el objeto desaparece, mientras que SoftReferences solo debería utilizarse cuando usaría una referencia normal, pero preferiría que se borre su objeto para que se agote. de la 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.

Supongo que los diseñadores de .Net consideraron que la diferencia era confusa para la mayoría de las personas o que las SoftReferences añaden más complejidad de la que realmente querían y decidieron dejarlas de lado.

Como nota al margen, AFAIK PhantomReferences están diseñados principalmente para uso interno por la máquina virtual y no están destinados para el uso real del cliente.

+1

Vea mis comentarios anteriores acerca de cuán útiles son SoftRefernces y cómo pueden permitirle codificar de manera más eficiente. Las referencias ficticias son para cualquier persona que realmente necesite hacer una limpieza post mortem de algún tipo. – user430788

3

Tal vez la clase ASP.NET Cache (System.Web.Caching.Cache) podría ayudar a lograr lo que desea? Se elimina automáticamente los objetos si no hay suficiente memoria:

He aquí un artículo que muestra cómo utilizar la clase de caché en una aplicación Windows Forms.

sido tomadas de: Equivalent to SoftReference in .net?

16

Creo que la razón fundamental de que NET no tiene referencias blandas es porque puede confiar en un sistema operativo con memoria virtual. Un proceso Java debe especificar su memoria máxima de sistema operativo (por ejemplo, con -Xmx128M), y nunca lleva 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 memoria RAM tiene cada proceso (al elegir qué páginas de memoria virtual almacenar en la memoria RAM o en el disco) y no el proceso en sí.

+0

Pero tal vez para .Net Compact tal cosa podría ser útil. – i486

11

Las referencias suaves de Java se utilizan en la creación de cachés sensibles a la memoria (no sirven para otro fin).

A partir de .NET 4, .NET tiene una clase System.Runtime.Caching.MemoryCache que probablemente satisfará tales necesidades.

+0

Este es un buen puntero y algo para estar en la parte superior de las respuestas. – user430788

+0

Es una buena adición, pero me pregunto por su flexibilidad. En general, estoy a favor de los mecanismos expuestos sobre las cajas negras de los concesionarios. Tienden a ser más útiles en la producción del mundo real. (El GC otorgado en sí mismo es generalmente una caja negra sellada, pero al menos Java le permite reemplazar todo el colector si realmente lo desea). – user430788

+0

Estoy de acuerdo, como punto general, prefiero mecanismos expuestos a cajas negras, que es una razón por la que mucho prefiero Java a C#. Pero, por otro lado, cada nuevo recolector de basura de Java requiere su propia implementación de SoftReferences que podría ser menos adecuada para sus propósitos que su GC actual. Y cambiar GC no es una tarea que deba tomarse a la ligera (al menos, en un entorno de baja pausa/baja latencia). – barneypitt

Cuestiones relacionadas