C# - Garbage Collection
Ok, so verstehe ich den stack und den heap (Werte live auf dem Stack Referenzen auf dem Heap).
Wenn ich deklarieren Sie eine neue Instanz einer Klasse, die dieses Leben auf dem heap, mit einem Verweis zu diesem Zeitpunkt im Arbeitsspeicher auf dem stack. Ich weiß auch, dass C# ist es die eigene Garbage Collection (ie. Es wird bestimmt, Wann eine Klasse instanziert ist nicht mehr in Gebrauch ist, und reaktiviert die Erinnerung).
Ich habe 2 Fragen:
- Ist mein Verständnis von Garbage Collection richtig?
- Kann ich meine eigenen? Wenn ja, gibt es tatsächlich einen Vorteil, es selbst zu tun oder sollte ich lass es einfach.
Ich Frage weil ich eine Methode in einer For-Schleife. Jedes mal, wenn ich über eine Schleife erstelle ich eine neue Instanz meiner Klasse. In meinem Kopf visualisiere ich alle diese Klassen liegen um in einem heap, nichts zu tun, aber unter dem Speicher und ich will Sie loswerden, so schnell wie ich kann, um zu halten Dinge ordentlich und sauber!
Verstehe ich das richtig oder bin ich etwas fehlt?
- Lassen Sie die GC tun es ist Sache. Das ist, was es dort für. Es sei denn, durch profiling, müssen Sie die Metriken, mit denen Sie ableiten, dass Sie müssen zum aufrufen des GC manuell.
- Wert-Typen auf dem stack, sagen Sie? blogs.msdn.com/b/ericlippert/archive/2010/09/30/...
- Lassen Sie es tun es ist Sache. Wenn die Profilerstellung zeigt an, es lohnt sich, betrachten Objekt-pooling.
- Sie verstehe eigentlich nicht den stack und den heap. Ich möchte Sie ermutigen, Lesen Sie blogs.msdn.com/b/ericlippert/archive/2009/04/27/... und blogs.msdn.com/b/ericlippert/archive/2010/09/30/...
- ist die neue Instanz verwendet, aus dem iterator-Bereich?
- Früher habe ich das gleiche Gefühl, als ich zu mir kam c# von c++. Es fühlt sich schmutzig af den ersten, aber Sie werden lernen, es zu ignorieren und lassen Sie den GC seine Sache tun.
- Programmierung Held - link setzen Sie so ein lächeln auf mein Gesicht, manchmal nur die Liebe sein falsch!
- Als ich zum ersten mal den Artikel, es blies meinen kleinen Geist.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube nicht, dass Sie verstehen, über den stack und den heap. Wenn die Werte live auf dem Stapel ist, wo kommt dann ein array von ganzen zahlen Leben? Ganze zahlen sind Werte. Wollen Sie mir erzählen, dass ein Integer-array hält, Integer auf dem stack? Wenn Sie return ein Integer-array aus einer Methode, sagen wir, mit zehn tausend Ganzzahlen in es, werden Sie mir erzählen, dass diejenigen, die zehn tausend Integer kopiert werden, auf den Stapel?
Werte live auf dem stack, wenn Sie live auf dem stack und auf dem heap, wenn Sie Leben auf dem heap. Die Idee, dass die Typ einer Sache, die zu tun hat mit die Lebensdauer der Speicherung ist Unsinn. Lagerorten, die kurzlebig gehen auf den stack; Lagerorten, die lange gelebt gehen über den Haufen, und das ist unabhängig von Ihrem Typ. Eine langlebige int zu gehen über den Haufen, genauso wie eine lange bestehende Instanz einer Klasse.
Warum wird die Referenz haben, gehen auf den Stapel? Wieder die Lebensdauer der Lagerung der Referenz nichts zu tun hat mit seiner Art. Wenn die Speicherung der Referenz ist lange gelebt, dann ist der Verweis geht auf dem heap.
Die Sprache C# nicht so tun; die CLR macht so.
Scheinen Sie zu glauben, eine Menge Lügen über die stack und heap, also Chancen stehen gut, Nein, es ist nicht.
Nicht in C# nicht.
Der springende Punkt bei der garbage collection befreit Sie von sorgen über das Aufräumen. Das ist, warum seine genannte "automatische garbage collection". Es räumt für Sie.
Wenn Sie besorgt sind, dass Ihre loops erstellen Sammlung Druck, und Sie möchten vermeiden Sammlung Druck aus performance-Gründen dann empfehle ich, dass Sie verfolgen einen pooling Strategie. Es wäre ratsam, beginnen Sie mit einem explizite pooling-Strategie; das ist:
eher als Versuch zu tun, eine automatische Zusammenlegung mit einer Wiederauferstehung des finalizer. Ich berate sowohl gegen Finalizer und Objekt Auferstehung im Allgemeinen, es sei denn, Sie sind ein Experte für die Fertigstellung Semantik.
Den pool natürlich reserviert eine neue Zerlegen, wenn es nicht in den pool. Wenn es eins in den pool, dann reicht es aus und entfernt es aus dem pool, bis es wieder in. (Wenn Sie vergessen zu legen, Zerlegen zurück in den pool, der GC wird man es irgendwann.) Im Rahmen einer pooling-Strategie, die Sie verursachen den Tisch, schließlich verschieben all die Frobs zu der generation, 2 heap, anstatt lose Sammlung Druck in der generation 0 heap. Die Sammlung Druck dann verschwindet, weil keine neuen Frobs zugeordnet werden. Wenn etwas anderes produzieren Sammlung Druck, die Frobs sind alle sicher in der gen 2-heap, wo Sie nur selten besucht.
Dies ist natürlich das genaue Gegenteil der Strategie, die Sie beschrieben; der ganze Sinn der pooling-Strategie ist dazu führen, dass Objekte zu hängen, um für immer. Hängende Objekte rund um forever ist ein gute Sache, wenn du gehst, Sie zu benutzen.
Natürlich nicht machen, diese Art von änderungen, bevor Sie wissen, über profiling, dass Sie ein performance-problem aufgrund collection Druck! Es ist selten, dass solch ein problem auf dem desktop CLR; es ist vielmehr häufiger auf der compact CLR.
Generell, wenn Sie die Art von person, die fühlt sich unwohl, wenn ein Speicher-manager clean-up für Sie auf Ihren Zeitplan, dann ist C# nicht die richtige Sprache für Sie. Prüfen, C, statt.
Dies ist eine Implementierung detail. Es gibt nichts zu stoppen ein .NET Framework von der Lagerung auf dem Stapel.
C# hat nichts mit diesem zu tun. Dies ist eine Dienstleistung, die von der CLR. VB.NET, F# usw alle haben noch die garbage collection.
CLR wird entfernen Sie ein Objekt aus dem Speicher, wenn Sie keine starken Wurzeln. Zum Beispiel, wenn Ihre Klasse eine Instanz außerhalb des Gültigkeitsbereichs, in deiner for-Schleife. Es wird ein paar herumliegen, aber Sie wird zusammengestellt bekommen schließlich, entweder durch garbage collection oder das Programm beenden.
Können Sie
GC.Sammeln
zu zwingen, eine Sammlung. Sollten Sie es nicht tun, weil es ist ein teurer Vorgang. Teurer als, dass ein paar Objekte, die Speicher belegen, ein bisschen länger als Sie sind, absolut notwendig. Die GC ist unglaublich gut, was es tut auf seine eigenen. Sie wird auch Kraft kurzlebigen Objekte zu fördern, um Generationen, Sie würden nicht normalerweise.First off, zu Erics bahnbrechenden Beitrag über Die Wahrheit über Wert-Typen
Zweitens auf die Garbage collection, der Sammler weiß weit mehr über Ihre Laufenden Programm, als Sie tun, versuchen Sie nicht zu raten, es sei denn, Sie sind in der unwahrscheinlich situation, dass Sie einen Speicherverlust.
Also zu deiner zweiten Frage, Nein, nicht versuchen zu "helfen" die GC.
Werde ich einen Beitrag zu diesem Effekt auf den CG und aktualisieren diese Antwort.
Kann man ja mit
GC.Collect
aber man sollte sich nicht. Die GC ist optimiert für Variablen, die kurz lebten, diejenigen, die in einer Methode und Variablen, die lange lebten, diejenigen, die in der Regel bleiben, um für die Lebensdauer der Anwendung.Variablen, die in-zwischen sind nicht wie üblich und nicht wirklich optimal für den GC.
Erzwingen ein GC.Sammeln Sie sind mehr wahrscheinlich dazu führen, dass Variablen, die im Gültigkeitsbereich werden in gezwungen, in die in-zwischen Staat, der das Gegenteil von Ihr zu erreichen versucht.
Auch von der MSDN-Artikel zu Schreiben High-Performance Management-Anwendungen : Eine Einführung
Ihr Verständnis für die Garbage Collection gut genug. Im Grunde ist der referenzierte Instanz gilt als out-of-scope sind und nicht mehr benötigt. Dabei bestimmt dieser, den Sammler zu entfernen wird eine referenzierte Objekt irgendwann in der Zukunft.
Es gibt keine Möglichkeit, zu erzwingen, dass der Garbage Collector sammeln Sie nur eine bestimmte Instanz. Sie können Fragen, es zu tun, seine normale "sammeln Sie alles, was möglich ist" operation
GC.Collect()
, aber sollte man nicht.; der garbage-collector ist effizient und effektiv, wenn Sie nur lassen Sie es auf seine eigenen Geräte.Insbesondere zeichnet sich am sammeln der Objekte, die haben eine kurze Lebensdauer, ebenso wie jene, die erstellt werden als temporäre Objekte. Sie sollten sich nicht Gedanken über die Erstellung von Lasten-Objekte in einer Schleife, es sei denn, Sie haben eine lange Lebensdauer, die verhindert, dass die sofortige Sammlung.
Finden Sie in diesem stellt sich die Frage, Hinblick auf die Stack-und Heap.
In Ihrem spezifischen Szenario, vereinbart, wenn Sie neue Objekte in einer for-Schleife, dann sind Sie gehen zu müssen, um sub-optimale Leistung. Sind die gespeicherten Objekte (oder anderweitig verwendet) innerhalb der Schleife, oder werden Sie entsorgt? Falls letzteres, können Sie diese optimieren, indem newing bis ein Objekt außerhalb der Schleife und wieder verwenden?
Hinblick auf können, Sie bei der Umsetzung Ihrer eigenen GC, es gibt keine expliziten delete-Schlüsselwort in C#, Sie müssen es verlassen, um die CLR. Sie können jedoch geben Sie Hinweise, wie, Wann, zu sammeln, oder, was zu ignorieren, während der Sammlung, allerdings würde ich lassen, es sei denn absolut notwendig.
Beste Grüße,
Lesen Sie den folgenden Artikel von Microsoft zu erhalten, das Niveau der Kenntnisse über die Garbage Collection in C#. Ich bin sicher, es wird helfen, wer braucht Informationen zu diesem Thema.
Memory Management und Garbage Collection im .NET Framework
Wenn Sie interessiert sind, in der Leistung von einigen Bereichen in Ihrem code beim schreiben von C# schreiben Sie unsicherer code. Sie haben ein plus an Leistung, und auch, in Ihren festen block, der garbage collector die die meisten wahrscheinlich nicht auftreten.
Garbage collection ist grundsätzlich Referenz-tracking. Ich kann mir nicht vorstellen, dass es eine guten Grund, warum Sie wollen würde, um es zu ändern. Sind Sie mit irgendeiner Art von problem, wo Sie finden, dass der Speicher nicht freigegeben wird? Oder vielleicht sind Sie auf der Suche für die dispose-Muster
Bearbeiten:
Ersetzt "reference counting" mit "reference tracking" - nicht zu verwechseln mit den Inkrement/Dekrement-Zähler auf Objekt Referenzieren/Dereferenzieren (z.B. aus Python).
Ich dachte, es war ziemlich üblich, um auf das Objekt verweisen, graph generation "Zählen", wie in dieser Antwort:
Warum kein Reference Counting + Garbage Collection in C#?
Aber ich nicht abholen-Handschuh (den) Eric Lippert 🙂