5 Stimmen

Aufteilen und Überwinden von großen Objekten für GC-Leistung

Bei meiner Arbeit diskutieren wir verschiedene Ansätze, um eine große Menge an verwaltetem Speicher (50-100 MB) zu bereinigen, wobei zwei Ansätze auf dem Tisch liegen (sprich: zwei erfahrene Entwickler können sich nicht einigen) und der Rest des Teams ist sich nicht sicher, welcher Ansatz wünschenswerter ist: Leistung oder Wartbarkeit.

Die gesammelten Daten bestehen aus vielen kleinen Objekten, ca. 30000, die wiederum andere Objekte enthalten; alle Objekte werden verwaltet. Es gibt viele Verweise zwischen diesen Objekten, einschließlich Ereignis-Handlern, aber nicht auf externe Objekte. Wir bezeichnen diese große Gruppe von Objekten und Verweisen als eine einzige Einheit, die als Blob bezeichnet wird.

Ansatz #1: Stellen Sie sicher, dass alle Verweise auf Objekte im Blob getrennt sind, und lassen Sie die GC den Blob und alle Verbindungen verarbeiten.

Ansatz #2: Implementieren Sie IDisposable für diese Objekte, rufen Sie dispose für diese Objekte auf und setzen Sie Verweise auf Nothing und remove-Handler.

Die Theorie hinter dem zweiten Ansatz ist, dass die großen, langlebigen Objekte länger brauchen, um im GC bereinigt zu werden. Wenn man also die großen Objekte in kleinere Häppchen zerlegt, kann der Garbage Collector sie schneller verarbeiten, was einen Leistungsgewinn bedeutet.

Ich denke, die grundlegende Frage ist die folgende: Ist es besser, große Gruppen miteinander verbundener Objekte zu zerlegen, um die Daten für die Garbage Collection zu optimieren, oder ist es besser, sie zusammenzuhalten und sich darauf zu verlassen, dass die Garbage Collection-Algorithmen die Daten für Sie verarbeiten?

Ich habe das Gefühl, dass dies ein Fall von Voroptimierung ist, aber ich kenne den GC nicht gut genug, um zu wissen, was ihm hilft oder ihn behindert.

Editar: Der "Blob" des Speichers ist nicht ein einziges großes Objekt, sondern viele kleine Objekte, die einzeln zugewiesen werden.

Ein wenig mehr Hintergrund, falls es hilfreich ist. Wir hatten "Lecks", da die Objekte nicht GCed wurden. Beide Ansätze lösen das Leck-Problem, aber an diesem Punkt ist es eine Debatte darüber, welcher besser geeignet ist.

9voto

Reed Copsey Punkte 536986

Der zweite Ansatz ist fehlerhaft - er geht davon aus, dass die Umsetzung IDisposable wird sich auf den Garbage Collector auswirken.

Leider, IDisposable hat nichts mit Garbage Collection zu tun . Es geht lediglich um die Freigabe unverwaltet Ressourcen. Es hört sich so an, als ob Ihr 2. Senior-Entwickler versucht, ein bisschen "zu clever" zu sein, als dass es ihm gut tut.

Der erste Ansatz sollte in Ordnung sein. Sobald Sie aufhören, den "Blob" zu referenzieren, wird jedes Objekt innerhalb des Blogs entwurzelt, und es sollte aufgeräumt werden. Dies kann zu einem unbestimmten Zeitpunkt geschehen, nachdem Sie die Referenz freigegeben haben (es sei denn, Sie weisen den GC explizit an, die Sammlung durchzuführen, was ich nicht empfehle). Die wechselseitigen Abhängigkeiten werden für Sie korrekt gehandhabt.

Nehmen wir an, dass die Implementierung von IDisposable und die Bereinigung der internen Referenzen theoretisch den Sammelprozess beschleunigen könnte. Wenn es einen (kleinen) Nettogewinn gibt, wird die Zeit, die für die Verarbeitung all dieser Daten aufgewendet wird, höchstwahrscheinlich jeden Gewinn in der GC überwiegen - und das ist wirklich außerhalb Ihres Geschäftsinteresses.

Ich vermute jedoch, dass es den Garbage Collector insgesamt eher verlangsamen als beschleunigen würde. Aufbrechen der Datenmenge in viele Objekte wird nicht helfen, die GC schneller laufen - es hat immer noch durch die Live-Referenzen, die in dieser Situation nicht anders sind zu verfolgen.

3voto

Hans Passant Punkte 894572

Beide Ansätze sind nicht sinnvoll. Die GC hat keine Probleme damit, zirkuläre Referenzen oder komplizierte Objektgraphen zu erkennen. Es macht keinen Sinn, Referenzen auf Null zu setzen. IDisposable trägt nicht zur Verbesserung der GC-Performance bei.

Wenn es einen Anhaltspunkt dafür gibt, wie Sie das Problem gelöst haben, dann ist es das Setzen von Ereignissen auf Null. Sie haben ein Händchen dafür, Objekte referenziert zu halten, wenn sie "rückwärts" implementiert werden. Mit anderen Worten: Sie halten den Verursacher des Ereignisses am Leben und reißen seine Clients ab. Die Abmeldung muss dann explizit erfolgen.

Aber der Versuch, dies zu erraten, war von Anfang an der falsche Ansatz. Jeder anständige Speicher-Profiler hätte Ihnen gezeigt, welche Referenz einen Graphen am Leben hielt.

2voto

zneak Punkte 129366

El IDisposable Schnittstelle hat nichts mit Garbage Collection zu tun.

Es kommt vor, dass einige Objekte (wie z. B. Dateiströme) Ressourcen enthalten, die sehr wertvoll sein können (da die Grenze für Dateideskriptoren für einen Prozess normalerweise viel niedriger ist als die Speichergrenze auf modernen Betriebssystemen). Der Garbage Collector erkennt sie jedoch nicht an. Wenn Ihnen also die Dateideskriptoren ausgehen, Sie aber noch über genügend Speicher verfügen, wird der Garbage Collector möglicherweise nicht ausgeführt.

El IDisposable Schnittstelle legt einen Mechanismus fest, mit dem Sie sicher sein können, dass alle nicht verwalteten Ressourcen, die mit einem verwalteten Objekt verbunden sind, freigegeben werden, sobald das Objekt tatsächlich unbrauchbar wird, und nicht erst, wenn der Garbage Collector beschließt, zu laufen.

Folglich hat es keine Auswirkungen auf die Art und Weise, wie Objekte im Müll gesammelt werden, wenn man sie zu IDisposable macht. Selbst bei Verwendung der Dispose Methode, um alle Referenzen zu löschen, hat nur geringe bis gar keine Auswirkungen auf die Garbage Collector-Läufe; durch das Löschen der Referenzen auf Ihren Blob werden alle kleineren Objekte auf einmal entwurzelt.

1voto

Stephen Kellett Punkte 2893

Microsoft deutet an, dass Dispose schneller ist als Finalize, wenn Sie Leistung für Objekte wünschen, die nicht verwaltete Ressourcen enthalten (Datei-Handles, GDI-Handles usw.). Ich glaube nicht, dass es das ist, was Sie zu erreichen versuchen (Sie haben nichts über nicht verwaltete Ressourcen gesagt).

Lassen Sie die GC ihre Arbeit machen (während ich dies tippe, erscheinen zwei andere Antworten, die so ziemlich das Gleiche sagen).

1voto

vittore Punkte 17185

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X