Unerwünschte Müllsammlung

7

In einem Titel "Erzwingen einer Garbage Collection" aus Buch "C # 2010 und die .NET 4 Platform" von Andrew Troelsen geschrieben:

"Der eigentliche Zweck des Garbage Collectors von .NET besteht darin, den Speicher für uns zu verwalten. In einigen sehr seltenen Fällen kann es jedoch sinnvoll sein, eine Garbage Collection mithilfe von GC.Collect () programmgesteuert zu erzwingen.

• Ihre Anwendung wird gerade in einen Codeblock eintreten, den Sie nicht durch eine mögliche Garbage-Collection unterbrochen haben möchten. ... "

Aber hör auf! Gibt es einen solchen Fall, wenn Garbage Collection unerwünscht ist? Ich habe sowas nie gesehen / gelesen (wegen meiner kleinen Entwicklungserfahrung natürlich). Wenn du während deiner Übung so etwas gemacht hast, bitte teile es. Für mich ist das ein sehr interessanter Punkt.

Danke!

    
Arterius 05.01.2012, 17:58
quelle

6 Antworten

5

Ich betreibe eine rezeptbezogene Website, und ich speichere eine riesige Grafik von Rezepten und deren Verwendung im Speicher. Aufgrund der Art, wie ich diese Informationen für einen schnellen Zugriff schwenke, muss ich mehrere Gigs von Daten in den Speicher laden, wenn die Anwendung geladen wird, bevor ich die Daten in einem sehr optimierten Graphen organisieren kann. Ich erstelle eine riesige Menge kleiner Objekte auf dem Heap, die, sobald der Graph erstellt wurde, nicht mehr erreichbar sind.

Dies ist alles erledigt, wenn die Webanwendung geladen wird, und dauert wahrscheinlich 4-5 Sekunden. Nachdem ich das getan habe, rufe ich GC.Collect(); an, weil ich lieber den ganzen Speicher zurückfordern würde, anstatt alle Threads während einer eingehenden HTTP-Anfrage zu blockieren, während der Garbage Collector alle diese kurzlebigen Objekte ausräumt. Ich denke auch, dass es besser ist, jetzt aufzuräumen, da der Heap zu dieser Zeit wahrscheinlich weniger fragmentiert ist, da meine App bisher noch nichts anderes gemacht hat. Das Verzögern kann dazu führen, dass viel mehr Objekte erstellt werden und der Heap mehr komprimiert werden muss, wenn GC automatisch ausgeführt wird.

Außerdem bin ich in meinen 12 Jahren .NET-Programmierung nie auf eine Situation gestoßen, in der ich den Garbage Collector zum Laufen zwingen wollte.

    
Mike Christensen 05.01.2012, 18:04
quelle
7

Ja, es gibt durchaus einen Fall, in dem die Garbage-Collection unerwünscht ist: wenn ein Benutzer darauf wartet, dass etwas passiert, und er länger warten muss, weil der Code erst dann ausgeführt werden kann, wenn die Garbage Collection abgeschlossen ist.

Das ist der Punkt von Troelsen: Wenn Sie einen bestimmten Punkt haben, an dem Sie wissen, dass ein GC nicht problematisch ist und wahrscheinlich in der Lage ist, erhebliche Mengen an Müll zu sammeln , dann ist es kann eine gute Idee sein, es zu provozieren, um zu vermeiden, dass es zu einem weniger günstigen Zeitpunkt ausgelöst wird.

    
Jon Skeet 05.01.2012 18:00
quelle
3

Die Empfehlung ist, dass Sie Collect nicht explizit in Ihrem Code aufrufen sollten. Können Sie Umstände finden, wo es nützlich ist?

Andere haben einige ausführlich beschrieben, und es gibt keinen Zweifel mehr. Das erste, was zu verstehen ist, ist mach es nicht . Es ist ein letzter Ausweg, untersuchen Sie andere Optionen, erfahren Sie, wie GC arbeitet, wie Ihr Code beeinflusst wird, und befolgen Sie die Best Practices für Ihre Designs.

Wenn Sie Collect am falschen Punkt aufrufen, wird Ihre Leistung schlechter. Schlimmer noch, wenn Sie sich darauf verlassen, wird Ihr Code sehr fragil. Die seltenen Bedingungen, die erforderlich sind, um einen Aufruf von Collect nützlich oder zumindest nicht schädlich zu machen, können durch eine einfache Änderung des Codes vollständig rückgängig gemacht werden, was unerwartete OOMs, eine langsame Performanz usw. zur Folge hat.

    
Tony Hopkinson 05.01.2012 18:03
quelle
2

Ich rufe es vor Leistungsmessungen auf, damit der GC die Ergebnisse nicht verfälscht.

Eine andere Situation sind Unit-Tests, die auf Speicherlecks testen:

%Vor%

Abgesehen davon, habe ich keine Situation gefunden, in der es tatsächlich hilfreich wäre Vor allem im Produktionscode sollte GC.Collect niemals IMHO gefunden werden.

    
Matthias 05.01.2012 18:06
quelle
1

Es wäre sehr selten, aber GC kann ein mäßig teurer Prozess sein. Wenn also ein bestimmter Bereich zeitsensitiv ist, wollen Sie diesen Bereich nicht durch GC unterbrechen lassen.

    
Davy8 05.01.2012 18:02
quelle
1
  

Ihre Anwendung wird gerade in einen Codeblock eintreten, den Sie nicht verwenden   möchte durch eine mögliche Müllsammlung unterbrochen werden. ...

Ein sehr verdächtiges Argument (das trotzdem viel benutzt wird).

Windows ist kein Echtzeit-Betriebssystem. Ihr Code (Thread / Prozess) kann immer vom OS-Scheduler vorweggenommen werden. Sie haben keinen garantierten Zugriff auf die CPU.

Es läuft also darauf hinaus: Wie ist die Zeit für einen GC-Lauf mit einem Zeitfenster (~ 20 ms) vergleichbar?

Es gibt sehr wenig harte Daten darüber, ich habe ein paar Mal gesucht.

Aus meiner eigenen Beobachtung (sehr informell) ist eine Gen-0-Sammlung & lt; 40 ms, normalerweise viel weniger. Ein vollständiges Gen-2 kann in ~ 100 ms laufen, wahrscheinlich mehr.

Das Risiko, vom GC unterbrochen zu werden, liegt also in der gleichen Größenordnung wie bei einem anderen Prozess. Und Sie können Letzteres nicht kontrollieren.

    
Henk Holterman 06.01.2012 13:58
quelle

Tags und Links