Frage

Auch wenn ich die ernsthaften Auswirkungen tun verstehe mit dieser Funktion zu spielen (oder zumindest das ist, was ich denke), ich sehe nicht, warum es eines dieser Dinge immer, dass respektable Programmierer nicht immer verwenden, auch diejenigen, den don‘ t sogar wissen, was es für.

Nehmen wir an, ich entwickle eine Anwendung, bei der Speichernutzung extrem variiert je nachdem, was der Benutzer tut. Der Applikations-Lebenszyklus lassen sich in zwei Hauptphasen unterteilt werden: Bearbeitung und Echtzeitverarbeitung. Während der Bearbeitungsphase wird angenommen, dass Milliarden oder sogar Billionen von Objekten erstellt werden; einige von ihnen kleine und einige von ihnen nicht, einige haben kann Finalizers und einige können nicht, und nehmen wir an, ihre Lebensdauern von wenigen Millisekunden bis lange Stunden variieren. Als nächstes entscheidet der Benutzer auf die Echtzeitstufe zu wechseln. An dieser Stelle sei angenommen, dass die Leistung spielt eine fundamentale Rolle und die geringste Veränderung in der Strömung des Programms könnte katastrophale Folgen nach sich ziehen. Objekterstellung wird dann auf das mögliche Minimum reduziert durch Objekt-Pools verwendet und die so aber dann die GC Chimes in unerwartet und wirft es weg, und jemand stirbt.

Die Frage: In diesem Fall wäre es nicht klug, GC.Collect () aufrufen, bevor die zweite Stufe der Eingabe

Schließlich sind diese beiden Phasen überlappen nie in der Zeit miteinander und alle die Optimierung und Statistiken der GC würde hier wenig nützen gesammelt haben könnte ...

Hinweis: Wie einige von Ihnen haben darauf hingewiesen, .NET möglicherweise nicht die beste Plattform für eine Anwendung so sein, aber das ist über den Rahmen dieser Frage. Die Absicht ist es zu klären, ob ein GC.Collect () -Aufruf Gesamtverhalten / Leistung einer Anwendung oder nicht verbessern kann. Wir stimmen alle darin überein, dass die Umstände, unter denen man so etwas tun würde, sind extrem selten, aber dann wieder, versucht der GC zu erraten, und tut es sehr gut, die meiste Zeit, aber es ist noch zu erraten.

Danke.

War es hilfreich?

Lösung

Von Rico Blog ...

  

Rule # 1

     

Sie nicht.

     

Das ist wirklich die wichtigste   Regel. Es ist fair zu sagen, dass die meisten   Verwendungen von GC.Collect () sind eine schlechte Idee   und ich ging in die im Detail in   das ursprüngliche Posting so werde ich nicht wiederholen   das alles hier. Also lassen Sie uns bewegen auf ...

     

Rule # 2

     

Betrachten GC.Collect () aufgerufen wird, wenn einige   Nicht-wiederkehrendes Ereignis hat gerade passiert   und dieses Ereignis ist sehr wahrscheinlich   viele alte Gegenstände verursacht   sterben.

     

Ein klassisches Beispiel dafür ist, wenn Sie   Schreiben einer Client-Anwendung und Sie   zeigen eine sehr große und komplizierte   Form, die eine Menge von Daten zugeordnet ist   damit. Ihr Benutzer hat nur   interagierten potenziell mit diesem Formular   Erstellen einige große Objekte ... Dinge   wie XML-Dokumente oder ein großer DataSet   oder zwei. Wenn das Formular schließt diese   Objekte sind tot und so GC.Collect ()   wird zurückfordern den Speicher zugeordnet   mit ihnen ...

So ist es wie dieser Situation klingt fallen kann nach Regel # 2, Sie wissen, dass es einen Moment in der Zeit, wo viele alte Gegenstände sind gestorben, und es ist nicht wiederkehrende. Doch vergessen Sie nicht, Rico Abschiedsworte.

  

Rule # 1 sollte Trumpf Regel # 2 ohne   starke Beweise.

Messen, messen, messen.

Andere Tipps

Wenn Sie GC.Collect () in der Produktion Code aufrufen erklären Sie im Wesentlichen, dass Sie mehr als die Autoren des GC kennen. Dies kann der Fall sein. Doch in der Regel ist es nicht, und daher dringend abgeraten.

Wie wäre es also, wenn Sie COM-Objekte wie MS Word oder MS Excel von .NET verwenden? Ohne Aufruf GC.Collect nach den COM-Objekten veröffentlichen wir haben festgestellt, dass die Word- oder Excel-Anwendungsinstanzen existieren noch.

In der Tat der Code, den wir verwenden, ist:

 
Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

So, dass eine falsche Verwendung des Garbage Collector sein würde? Wenn ja, wie bekommen wir die Interop-Objekte zu sterben? Auch wenn es nicht gemeint ist wie folgt verwendet werden: Warum ist das GC der Collect Methode sogar Public?

Nun, die GC eine jener Dinge, die ich mit Liebe / Hass-Beziehung haben. Wir haben es in der Vergangenheit durch VistaDB gebrochen und darüber gebloggt. Sie haben es festgelegt, aber es dauert eine lange Zeit, um Korrekturen von ihnen auf Dinge wie diese.

Die GC ist komplex, und ein one size fits all Ansatz ist sehr, sehr hart an etwas so groß abziehen. MS hat eine ziemlich gute Arbeit geleistet, aber es ist möglich, den GC manchmal zu täuschen.

Generell sollte man keine Collect hinzufügen, wenn Sie für eine Tatsache wissen, dass Sie nur eine Tonne Speicher entleert, und es wird auf eine Midlife-Crisis wenn der GC nun aufgeräumt nicht erhalten.

Sie können die gesamte Maschine mit einer Reihe von schlechten GC.Collect Aussagen vermasseln. Die Notwendigkeit einer Collect-Anweisung weist fast immer auf einen größeren zugrunde liegenden Fehler. Der Speicherverlust hat in der Regel mit Referenzen und einem Mangel an Verständnis zu tun, wie sie funktionieren. Oder mit der IDisposable auf Objekte, die es nicht brauchen und eine wesentlich höhere Last auf dem GC setzen.

Achten Sie genau das% der Zeit in GC durch die System-Leistungsindikatoren ausgegeben. Wenn Sie Ihre Anwendung unter Verwendung von 20% oder mehr seiner Zeit in der GC sehen haben Sie ernsthafte Objekt-Management-Themen (oder ein anormales Nutzungsmuster). Sie wollen immer die Zeit zu minimieren, die GC verbringt, weil es Ihre gesamte App beschleunigen wird.

Es ist auch wichtig zu beachten, dass der GC auf Servern als Workstations unterschiedlich ist. Ich habe eine Reihe von kleinen schwierig zu sehen Probleme aufzuspüren mit Menschen nicht beiden Tests (oder nicht einmal bewusst, dass sie sind zwei von ihnen).

Und wie voll zu sein in meiner Antwort wie möglich auch unter Mono testen sollten, wenn Sie diese Plattform als auch ausgerichtet sind. Da es sich um eine ganz andere Anwendung ist, kann es ganz andere Probleme auftreten, dass die MS-Implementierung.

Es gibt Situationen, in denen es sinnvoll, aber im Allgemeinen sollte es vermieden werden. Man könnte es auf GOTO vergleichen, oder Reiten ein Moped. Sie tun es, wenn Sie müssen, aber Sie nicht sagen, Ihre Freunde über sie

Aus meiner Erfahrung ist es nie ratsam gewesen, einen Anruf zu GC.Collect () in der Produktion Code zu machen. In Debugging, ja, es hat seine Vorteile potenzielle Speicherlecks zu verdeutlichen. Ich denke, meine eigentliche Grund ist, dass die GC geschrieben wurde und optimiert von Programmierern viel klüger dann ich, und wenn ich an einen Punkt, dass ich glaube, ich brauche GC.Collect () aufrufen es ein Anhaltspunkt ist, dass ich Weg gegangen sind irgendwo. In Ihrer Situation klingt es nicht wie Sie tatsächlich Speicherprobleme haben, nur, dass Sie besorgt sind, was Instabilität der Sammlung auf den Prozess bringen. Sehen, dass es Gegenstände reinigen, noch im Gebrauch nicht, und dass es sehr schnell steigenden und Senken Anforderungen passt, würde ich denken, dass Sie sich nicht um sie zu kümmern.

Einer der größten Gründe zu nennen GC.Collect (), wenn Sie nur ein bedeutendes Ereignis durchgeführt haben, die vielen Müll erzeugt, wie zum Beispiel, was Sie beschreiben. Der Aufruf GC.Collect () kann eine gute Idee, hier; Andernfalls verstehen die GC nicht, dass es ein ‚ein Mal‘ Ereignis ist.

Natürlich sollten Sie es profilieren, und überzeugen Sie sich selbst.

Nun, natürlich sollten Sie nicht Code mit Echtzeitanforderungen in Sprachen mit nicht-Echtzeit-Garbage-Collection schreiben.

In einem Fall mit gut definierten Stufen, gibt es kein Problem mit Auslösen des Garbage-Collector. Aber dieser Fall ist extrem selten. Das Problem ist, dass viele Entwickler werden versuchen, dies zu Papier über Probleme in einem Fracht-Kult-Stil zu verwenden, und das Hinzufügen es wird wahllos zu Leistungsproblemen führt.

Der Aufruf GC.Collect () zwingt den CLR einen Stapel zu Fuß zu tun, wenn jedes Objekt zu sehen truely durch Überprüfung Verweise freigegeben werden werden. Dadurch wird die Skalierbarkeit auswirken, wenn die Anzahl der Objekte hoch ist, und hat auch Garbage Collection auslösen zu oft bekannt. Vertrauen Sie auf die CLR und lassen Sie den Garbage Collector selbst ausgeführt werden, wenn angemessen.

Erstellen von Bildern in einer Schleife - auch wenn Sie verfügen aufrufen, wird der Speicher nicht wiederhergestellt. Müll sammelt jedes Mal. Ich ging von 1,7 GB Speicher auf meiner Fotobearbeitung App zu 24MB und Leistung ist hervorragend.

Es gibt absolut Zeit, die Sie brauchen GC.Collect zu nennen.

Infact, ich glaube nicht, es ist eine sehr schlechte Praxis GC.Collect zu nennen.
Es kann Fälle geben, wenn wir das brauchen. Nur zum Beispiel habe ich eine Form, die einen Thread läuft, die inturn Differnt Tabellen in einer Datenbank öffnet, extrahiert den Inhalt in einem BLOB-Feld in eine temporären Datei, um die Datei verschlüsseln, dann die Datei in ein Binary lesen und zurück in eine BLOB Feld in einer anderen Tabelle.

Die ganze Operation dauert ziemlich viel Speicher, und es ist nicht sicher, über die Anzahl der Zeilen und die Größe der Dateiinhalt in den Tabellen.
Früher habe ich OutofMemory Exception oft zu bekommen, und ich dachte, es wäre klug, in regelmäßigen Abständen GC.Collect basierend auf einer Zählvariable laufen. Ich erhöht einen Zähler und wenn ein bestimmtes Niveau erreicht ist, wird GC genannt keinen Müll zu sammeln, die sich gebildet haben können, und jede Speicher aufgrund unvorhergesehener Speicherlecks.

verloren zurückzufordern

Danach, denke ich, es funktioniert gut, atleast keine Ausnahme !!!
Ich rufe auf folgende Weise:

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).

Unter .net war die Zeit, eine Garbage Collection durchzuführen ist viel stärker auf die Menge an Material bezogen, die nicht Müll ist, als auf die Menge an Material, das ist. Tatsächlich, es sei denn ein Objekt überschreibt Finalize (entweder explizit oder über C # destructor), ist das Ziel eines WeakReference, sitzt auf dem Large Object Heap, oder ist etwas Besonderes in einem anderen gc bezogen, das einzige, was den Speicher zu identifizieren, in denen es sitzt wie ein Objekt ist die Existenz wurzelt Verweise auf sie ist. Andernfalls wird die GC Betrieb analog von einem Gebäude alles von Wert zu nehmen, und das Gebäude gesprengt, ein neues auf dem Gelände der alten Gebäude, und alle wertvollen Gegenstände in sie setzen. Der Aufwand, das Gebäude zu sprengen ist völlig unabhängig von der Menge an Müll in sie.

Folglich GC.Collect Aufruf geeignet ist, den Gesamtbetrag der Arbeit zu erhöhen, das System zu tun hat. Es wird das Auftreten der nächsten Sammlung verzögern, wird aber wahrscheinlich genauso viel Arbeit sofort die nächste Sammlung erforderlich wäre tun, wenn es aufgetreten ist; an dem Punkt, wenn die nächste Sammlung aufgetreten wäre, verbrachte die Gesamtmenge der Zeit sammeln wird etwa das gleiche gewesen wie hatte GC.Collect nicht genannt worden, aber das System wird einigen Müll angesammelt hat, die nachfolgende Sammlung verursacht früher erforderlich werden, als hatte GC.Collect nicht genannt.

Die Zeiten, ich GC.Collect wirklich nützlich zu sehen sein, wenn man entweder muss die Speichernutzung von Code messen (da der Speichernutzung Zahlen nach einer Sammlung nur dann wirklich sinnvoll sind), oder das Profil, das aus mehreren Algorithmen besser ist (Aufruf GC .Collect () vor jedem der mehrere Teilen des Codes ausgeführt wird, kann einen einheitlichen Basiszustand) sicherzustellen. Es gibt ein paar andere Fälle, in denen man die Dinge wissen, könnte der GC nicht, aber es sei denn, man ist ein Single-Threaded-Programm zu schreiben, gibt es keine Möglichkeit man wissen kann, dass ein GC.Collect Anruf, der eine Thread-Datenstrukturen Lebensmittel vermeiden“helfen würde, Krise Midlifecrisis ‚“ würde eine nicht dazu führen, andere Threads' Daten zu haben‘, die andernfalls vermieden worden wären.

Wir hatten ein ähnliches Problem mit der Garbage Collector nicht Müll zu sammeln und Speicher frei.

In unserem Programm wurden die Verarbeitung wir einige bescheidene Größe Excel-Tabellen mit OpenXML. Die Tabellen von 5 bis 10 „Blätter“ mit über 1000 Zeilen von 14 Spalten überall enthalten ist.

Das Programm in einer 32-Bit-Umgebung (x86) abstürzen würde mit einem "out of memory" -Fehler. Wir haben es in einer x64-Umgebung ausgeführt werden, aber wir wollten eine bessere Lösung.

Wir fanden ein.

Hier sind einige vereinfachte Codefragmente von dem, was nicht funktioniert und was funktioniert hat, wenn es explizit darum geht, die Garbage Collector Aufruf Speicher von angeordneten Objekte freizugeben.

Der Aufruf der GC von innen das Unterprogramm hat nicht funktioniert. Speicher wurde nie zurückgewonnen ...

 
For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

Durch Bewegen des GC Anruf außerhalb des Umfangs des Unterprogramms wurde die Garbage Collection und der Speicher freigegeben wurde.

 
For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

Ich hoffe, das hilft anderen, die mit der .NET Garbage Collection sind frustriert, wenn es angezeigt, die Anrufe zu ignorieren GC.Collect().

Paul Smith

Nichts ist falsch mit explizit für eine Sammlung aufrufen. Manche Leute wollen einfach wirklich glauben, dass, wenn es ein Service des Verkäufers ist, stelle es nicht infrage. Ach ja, und alle diese zufällig friert an den falschen Momenten Ihrer interaktiven Anwendung? Die nächste Version wird es besser machen!

einen Hintergrundprozess handelt von Speichermanipulation Letting Mittel mit nicht damit umgeht sie, wahr. Das bedeutet aber nicht logisch, dass es am besten ist für uns nicht damit beschäftigen sie unter allen Umständen. Die GC ist für die meisten Fälle optimiert. Das bedeutet aber nicht logisch, dass es in allen Fällen optimiert ist.

Haben Sie schon einmal beantworten eine offene Frage wie ‚welche ist die beste Sortieralgorithmus‘ mit einer endgültigen Antwort? Wenn ja, berühren Sie nicht die GC. Für diejenigen, die für die Bedingungen gefragt, oder gab ‚in diesem Fall‘ Typ Antworten, können Sie gehen über die GC zu lernen und wenn es zu aktivieren.

Muss ich sagen, habe ich Anwendung friert in Chrome und Firefox hatte, die die Hölle aus mir heraus, und selbst dann für einige Fälle vereiteln die Erinnerung wächst ungehindert - Wenn nur würden sie lernen, die Garbage Collector zu nennen - oder gab ich eine Taste, so dass, wie ich beginne, den Text einer Seite lesen ich es treffen kann und somit frei von gefriert für die nächsten 20 Minuten.

Ich glaube, Sie über das Szenario richtig sind, aber ich bin über die API nicht sicher.

Microsoft sagt, dass in solchen Fällen sollten Sie Speicherdruck hinzufügen als Hinweis auf die GC, dass es bald eine Sammlung durchführen soll.

Was ist los mit ihm? Die Tatsache, dass Sie zweite Mutmaßung der Garbage Collector und Speicherzuordner, die sich zwischen ihnen eine viel größere Vorstellung über Ihre Anwendung die tatsächlichen Speicherverbrauch zur Laufzeit als Sie.

Der Wunsch zu nennen GC.Collect () in der Regel für Fehler zu vertuschen versucht, Sie woanders gemacht!

Es wäre besser, wenn Sie feststellen, wo man Sachen zu entsorgen vergessen haben, nicht mehr brauchte.

Unterm Strich können Sie das Anwendungsprofil und sehen, wie diese zusätzlichen Sammlungen Dinge beeinflussen. Ich würde vorschlagen, obwohl bleiben weg von ihm, wenn Sie zum Profil gehen. Die GC ist so konzipiert, von sich selbst kümmern und so die Laufzeit entwickelt, können sie die Effizienz steigern. Sie wollen nicht einen Haufen Code rumhängen, dass die Arbeiten verhunzen kann und nicht in der Lage sein, die Vorteile dieser Verbesserungen zu nehmen. Es gibt ein ähnliches Argument für die Verwendung von foreach statt für, das ist, dass künftige Verbesserungen unter der Decke hinzugefügt werden können, um foreach und Ihr Code muss nicht in Anspruch nehmen zu ändern.

Der .NET Framework selbst war nie in einer Echtzeit-Umgebung ausgeführt werden entworfen. Wenn Sie wirklich in Echtzeit verarbeitet werden müssen entweder würden Sie eine eingebettete Echtzeit-Sprache verwenden, die nicht auf .NET basiert oder das .NET Compact Framework auf einem Windows CE-Gerät ausgeführt wird verwenden.

Das Schlimmste tut es ist Ihr Programm Einfrieren für ein bisschen machen. Also wenn das mit Ihnen in Ordnung ist, tun Sie es. Normalerweise ist es nicht erforderlich, für Thick-Client oder Web-Anwendungen mit meist Interaktion mit dem Benutzer.

ich gefunden habe, dass manchmal Programme mit langen Laufzeit-Threads oder Batch-Programmen, OutOfMemory Ausnahme erhalten, obwohl sie Gegenstände entsorgen richtig. Ein I Rückruf war eine Line-of-Business-Datenbank-Transaktionsverarbeitung; der andere war auf einem Hintergrund-Thread in einer dicken Client-Anwendung eine Indizierungsroutine zurück.

In beiden Fällen war das Ergebnis einfach: Nein GC.Collect, aus dem Speicher, konsequent; GC.Collect, einwandfreie Leistung.

Ich habe es versucht, Probleme mit dem Speicher mehr anderen Zeiten zu lösen, ohne Erfolg. Ich nahm es heraus.

Kurz gesagt, tun Sie es nicht in, es sei denn Sie Fehler bekommen. Wenn Sie es in setzen und es ist das Speicherproblem nicht beheben, nehmen Sie es wieder heraus. Denken Sie daran, in Release-Modus zu testen und vergleichen Äpfel mit Äpfeln.

Die einzige Zeit, die Dinge schief gehen können mit diesem ist, wenn man darüber moralistisch bekommen. Es ist kein Problem Wert; Viele Programmierer sind gestorben und gegangen direkt in den Himmel mit vielen unnötigen GC.Collects in ihrem Code, die sie überlebt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top