2008-11-27 10 views
13

Ich liebe WeakReference's wirklich. Aber ich wünschte, es gäbe einen Weg, der CLR zu sagen, wie viel (sagen wir auf einer Skala von 1 bis 5), wie schwach Sie die Referenz betrachten. Das wäre brillant.Warum hat .NET weder eine SoftReference noch eine WeakReference wie Java?

Java hat SoftReference, WeakReference und ich glaube auch eine dritte Art namens "Phantom-Referenz". Das sind 3 Ebenen genau dort, wo der GC einen anderen Verhaltensalgorithmus hat, wenn er entscheidet, ob das Objekt den Hacken bekommt.

Ich denke an die Unterklasse von .NET WeakReference (glücklicherweise und etwas bizzarely es ist nicht versiegelt), um eine Pseudo-SoftReference, die auf einem Ablauftimer oder etwas basiert.

+2

Vielleicht, wenn Sie erklären, welches Problem Sie lösen möchten, erhalten Sie möglicherweise einige Antworten mit guten Lösungen. Normalerweise ist es keine gute Idee, auf dieser Granularitätsebene zu arbeiten, und eine Form des Ablaufcaches ist geeigneter, aber alles hängt von dem Problem ab. –

Antwort

4

Meine Vermutung, warum dies nicht schon da ist, wäre Einfachheit. Die meisten Menschen, denke ich, würden es als Tugend bezeichnen, dass es nur eine Art von Referenz gibt, nicht vier.

+3

SoftReferences sind EXTREM nützlich, da sie gc-bewusstes Speicher-Caching ermöglichen. Die meisten Leute, die wirklich verstehen, wofür sie gut sind, würden sie gerne haben. In Java-Code verwende ich SoftReference VIEL häufiger als WeakReference – user430788

0

Suchen Sie nach der 'trackResurrection' Option, die vielleicht an den Konstruktor übergeben wurde?

Die GC-Klasse bietet auch einige Unterstützung.

1

Vielleicht sollte es eine Eigenschaft geben, in der Sie angeben können, welche Generation das Objekt> = vor der Erfassung angibt. Wenn Sie also 1 angeben, ist dies die schwächste mögliche Referenz. Wenn Sie jedoch 3 angeben, muss es mindestens 3 vorherige Sammlungen überleben, bevor es für die Sammlung selbst in Betracht gezogen werden kann.

Ich dachte, die Track Ressurection Flag war dafür nicht gut, weil das Objekt zu diesem Zeitpunkt bereits fertiggestellt wurde? obwohl sich irren kann ...

(PS: Ich bin der OP, nur unterzeichnet PITA, dass es nicht Ihre Geschichte von „unregistered“ Konten nicht erben..)

4

eine WeakReference mit unterschiedlichem Having Schwäche (Priorität) klingt nett, aber auch könnte die GC-Arbeit schwieriger, nicht einfacher. (Ich habe keine Ahnung von den GC-Interna, aber) Ich würde davon ausgehen, dass es eine Art zusätzliche Zugriffsstatistiken für WeakReference-Objekte gibt, damit der GC sie effizient bereinigen kann (z. B. könnte er die am wenigsten genutzten Objekte entfernen) zuerst).

Mehr als wahrscheinlich würde die hinzugefügte Komplexität nichts effizienter machen, da der effizienteste Weg ist, die selten verwendeten WeakReferences zuerst loszuwerden. Wenn Sie eine Priorität zuweisen könnten, wie würden Sie es tun? Das riecht nach einer vorzeitigen Optimierung: Der Programmierer weiß die meiste Zeit nicht wirklich und rät; Das Ergebnis ist ein langsamerer GC-Sammlungszyklus, bei dem wahrscheinlich die falschen Objekte zurückgewonnen werden.

Es stellt sich jedoch die Frage, ob es wirklich eine gute Verwendung von WeakReference ist, wenn Sie sich um das WeakReference.Target-Objekt kümmern, das zurückgewonnen wird.

Es ist wie ein Cache. Du schubst Sachen in den Cache und fragst den Cache, um es nach x Minuten zu veralten, aber die meisten Caches garantieren niemals, dass es überhaupt in der Nähe bleibt. Es garantiert nur, dass es, wenn es dies tut, es gemäß der angeforderten Richtlinie ablaufen wird.

+0

Der Unterschied ist, dass die Verwendung von SoftReference zu Cache können Sie Dinge zu halten, solange es genug Speicher für sie, aber entsorgen sie wenn nicht. Es ist eine * viel * effizientere Lösung als eine Auszeit in einem Cache. – user430788

+0

@ user430788 Ich denke, du verpasst meinen Kommentar zu Caches. Ein Cache könnte bereits WeakReference verwenden, aber die Stalenness könnte auch für zwischengespeicherte Elemente gelten. Vom Standpunkt des Cache-Konsumenten garantiert ein Cache normalerweise nicht, dass Elemente im Cache verbleiben.Entwickler beschweren sich bereits über den GC, also war das C# -Team vielleicht der Meinung, dass das Hinzufügen neuer Ebenen schwacher Referenzen (soft, phantom) nicht ausreicht. Wie immer, Eric Lippert's http://blogs.msdn.com/b/ericlippert/archive/2003/10/28/how-many-microsoft-employees-does-it-take-to-change-a-lightbulb.aspx ist eine gute Lektüre für Einblicke in C# -Features. –

+1

Robert, ich fürchte, du hast mich überhaupt nicht verstanden. Nein, ein Cache garantiert nicht, dass Dinge im Cache verbleiben. Das ist der Punkt. Aber ein Cache, der nur auf Zeit basiert, macht keinen guten Job, um zu bestimmen, was im Speicher sein sollte und was nicht. Es spült Dinge ohne Grund. Ein Cache, der auf Speicheranforderungen basiert, speichert Daten viel besser, es sei denn, er muss wirklich entfernt werden. Sie könnten selbst einen LRU-Cache implementieren, aber dafür müssten Sie Ihrer Anwendung Pseudo-Memory-Management-Code hinzufügen. Es ist viel effizienter, den GC, der bereits Speicher verwaltet, den Cache verwalten zu lassen. – user430788

0

Ich weiß nicht, warum .NET keine Softreferenzen hat. ABER in Java Softreferenzen werden IMHO überstrapaziert. Der Grund dafür ist, dass Sie zumindest in einem Anwendungsserver pro Anwendung beeinflussen können, wie lange Ihre Softreferenzs live sind. Das ist derzeit in Java nicht möglich.

+0

Auf HotSpot gibt es eine Option, um dies leicht zu konfigurieren: -XX: SoftRefLRUPolicyMSPerMB = xyz. Siehe http://java.sun.com/docs/hotspot/HotSpotFAQ.html#gc_softrefs –

2

Vergessen Sie nicht, dass Sie auch Ihre Standardreferenzen haben (die, die Sie täglich verwenden). Dies gibt Ihnen eine weitere Ebene.

WeakReferences sollte verwendet werden, wenn es Ihnen nicht wirklich wichtig ist, wenn das Objekt verschwindet, während SoftReferences eigentlich nur dann verwendet werden sollten, wenn Sie eine normale Referenz verwenden würden, aber Sie lieber Ihr Objekt löschen möchten der Erinnerung. Ich bin mir nicht sicher über die Besonderheiten, aber ich vermute, dass der GC normalerweise durch SoftReferences, aber nicht durch WeakReferences bei der Bestimmung der Objekte läuft, aber wenn der Speicher knapp wird, werden auch die SoftReferenzen übersprungen.

Meine Vermutung ist, dass die .NET-Designer der Meinung waren, dass der Unterschied für die meisten Leute verwirrend sei und dass SoftReferences mehr Komplexität hinzufügen, als sie wirklich wollten und beschlossen, sie wegzulassen.

Als eine Nebenbemerkung sind AFAIK PhantomReferences hauptsächlich für den internen Gebrauch durch die virtuelle Maschine bestimmt und sind nicht für die tatsächliche Client-Nutzung gedacht.

+1

Siehe meine Kommentare oben, wie nützlich SoftReferenzen sind und wie sie Ihnen erlauben, effizienter zu programmieren. Phantom Referenzen sind für jeden, der wirklich post mortem Aufräumen irgendeiner Art tun muss. – user430788

3

Vielleicht kann die ASP.NET-Cache-Klasse (System.Web.Caching.Cache) helfen zu erreichen, was Sie wollen? Es automatisch Objekte entfernen, wenn der Speicher zur Neige geht:

Hier ist ein Artikel, der zeigt, wie die Cache-Klasse in einem Windows-Anwendung bildet verwenden.

aus zitiert: Equivalent to SoftReference in .net?

16

ich der wesentliche Grund glauben, dass NET nicht weich Referenzen hat, weil es auf einem Betriebssystem mit virtuellem Speicher verlassen können. Ein Java-Prozess muss seinen maximalen OS-Speicher angeben (z. B. mit -Xmx128M), und er muss niemals mehr OS-Speicher als das dauert. Während ein NET-Prozess weiterhin OS-Speicher benötigt, den das Betriebssystem mit Festplatten-gesichertem virtuellem Speicher versorgt, wenn der RAM-Speicher leer ist. Wenn NET weiche Verweise zuließ, dann würde die .NET-Laufzeit nicht wissen, wann sie freigegeben werden sollten, es sei denn, sie hat entweder tief in das Betriebssystem geblättert, um zu sehen, ob ihr Speicher tatsächlich ausgelagert ist (eine unangenehme OS/CLR-Abhängigkeit) Geben Sie einen maximalen Speicherbedarf für den Prozessspeicher an (z. B. ein Äquivalent von -Xmx). Ich nehme an, dass Microsoft -Xmx nicht zu NET hinzufügen möchte, weil sie denken, dass das Betriebssystem entscheiden sollte, wie viel RAM jeder Prozess erhält (durch Auswahl der virtuellen Speicherseiten im RAM oder auf der Festplatte) und nicht den Prozess selbst.

+0

Aber vielleicht für .Net Compact könnte so etwas sinnvoll sein. – i486

11

Java SoftReferences werden bei der Erstellung von speicherempfindlichen Caches verwendet (sie dienen keinem anderen Zweck).

Ab .NET 4 hat .NET eine Klasse System.Runtime.Caching.MemoryCache, die wahrscheinlich solche Anforderungen erfüllen wird.

+0

Dies ist ein wirklich guter Zeiger und etwas an der Spitze der Antworten zu sein. – user430788

+0

Es ist eine nette Ergänzung, aber ich wundere mich über seine Flexibilität. Ich bin im Allgemeinen für offengelegte Mechanismen über Händler Black Boxes. Sie sind in der realen Produktion nützlicher. (Gewährt GC selbst ist eine versiegelte Black Box, aber zumindest Java lässt Sie den gesamten Kollektor ersetzen, wenn Sie wirklich wollen.) – user430788

+0

Ich stimme zu, im Allgemeinen - ich bevorzuge offengelegte Mechanismen zu Black Boxes, was ein Grund ist, ich viel lieber Java zu C#. Auf der anderen Seite benötigt jeder neue Java-Garbage-Collector eine eigene Implementierung von SoftReferences, die leicht weniger für Ihre Zwecke geeignet sind als Ihr aktueller GC. Und das Wechseln von GC ist kein Unternehmen, das leichtfertig genommen werden sollte (zumindest in einer Umgebung mit geringer Pause/niedriger Latenz). – barneypitt