Kann ich die Gen 2 GC-Sammlung in .NET unterdrücken?

  • Mein Programm weist eine sehr große Anzahl von Instanzen auf, die eine langlebige DAWG umfassen. Während des Aufbaus dieser DAWG verlangsamt sich der Fortschritt um das 100-fache, was perfekt mit der Ausführung von Gen 2-GC-Sammlungen von .NET korreliert. Während dieser Zeiträume beträgt die "% -Zeit in GC" 99,5%, und die "Gesamtsammlung von Gen 2" erhöht sich alle paar Sekunden. Nach mehreren aufeinanderfolgenden Gen-2-Sammlungen werden sie ohne ersichtlichen Grund nicht mehr ausgelöst und das Programm beschleunigt sich erneut. Ein paar Minuten später wird der Zyklus neu gestartet.

    Die Anzahl der von mir erstellten Instanzen liegt in der Größenordnung von 25 Millionen, und sie beanspruchen mehrere GB RAM, daher ist es nicht zu überraschend dass die Gen-2-Sammlungen so lange dauern. Überraschend ist, dass die Gen-2-Sammlungen in "Zügen" abgelegt werden und ständig ausgelöst werden.

    Kann ich dies irgendwie verhindern, ohne mein Vorgehen völlig neu zu überdenken? Vielleicht gibt es eine Möglichkeit, .NET zu bitten, die Gen-2-Sammlungen bis auf weiteres zu sperren? Abgesehen von diesen Vorkommnissen wird das Programm sehr effizient ausgeführt. Daher ist .NET dieser Aufgabe abgesehen von diesem unglücklichen Verhalten im Eckfall eindeutig gewachsen.

    (Ich habe versucht, GCSettings.LatencyMode auf "Einstellung" zu setzen GCLatencyMode.Batch, aber das Problem blieb bestehen. Die Menge an freiem physischem RAM zum Zeitpunkt des Beginns der GCs liegt bei etwa 1 GB. Dies ist auf einem 64-Bit-Computer.)

    22 November 2011
    Roman Starkov
4 answers
  • In .NET 4.5+ können Sie mit den neuen Optionen GCLatencyMode Ihre Präferenz für weniger Gen 2-Sammlungen festlegen.

     GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;
     

    Weitere Informationen hier:

    http://blogs.msdn.com /b/dotnet/archive/2012/07/20/the-net-framework-4-5-incles-se-new-garbage-collector-enhancements-for-client-and-server-apps.aspx

    Meine App kann Pausen während eines bestimmten Zeitfensters nicht tolerieren.

    Eine wachsende Teilmenge .NET-Entwickler haben kommerzielle Apps und - Dienste entwickelt, die Ergebnisse gemäß den definierten geschäftlichen Anforderungen oder SLAs liefern. Aktienmärkte sind Beispiele für Dienstleistungen, die bei sehr offenen Märkten sehr zeitnahe Ergebnisse liefern müssen. In der Regel leisten diese Apps erhebliche Arbeit, wenn sie Ergebnisse mit geringer Latenz liefern möchten. Sie tolerieren jedoch keine auffälligen Pausen aufgrund einer Sammlung.

    Unsere Kunden haben uns gesagt, dass sie mehr Speicher auf ihren Servern bereitstellen würden, wenn dies zu einer längeren Entfernung führen würde Pausenzeiten (die normalerweise durch vollständig blockierende GCs eingeführt werden). In .NET Framework 4.5 haben wir diese Option bereitgestellt, indem wir den Modus SustainedLowLatency eingeführt haben, durch den das vollständige Blockieren von GCs vermieden wird. Dieser Modus ist auch für den Workstation-GC in .NET Framework 4 über Update 4.0.3 verfügbar.

    Wenn die Einstellung "SustainedLowLatency" aktiviert ist, wird Generation 0 Sammlungen der Generation 1 und Hintergrundgenerierung 2 treten weiterhin auf und verursachen normalerweise keine merklichen Pausenzeiten. Eine blockierende Generation 2 -Sammlung wird nur ausgeführt, wenn der Computer über wenig Arbeitsspeicher verfügt oder wenn die App einen GC durch Aufrufen von GC.Collect () auslöst. Es ist wichtig, dass Sie Apps, die die SustainedLowLatency-Einstellung verwenden, auf Computern bereitstellen, die über ausreichenden Arbeitsspeicher verfügen, damit diese die Anforderungen erfüllen

    08 May 2015
    jocull
  • Ab .NET 4.6 können Sie versuchen, die Garbage Collection in einem Codebereich mit den Methoden GC.TryStartNoGCRegion und GC.EndNoGCRegion zu unterbinden.

     [pre> try
    {
        GC.TryStartNoGCRegion(TOTAL_SIZE, true);
    
        <No GC region code here>
    }   
    finally
    {
        if (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) GC.EndNoGCRegion();
    }
     

    Weitere Informationen zu den Argumenten und möglichen Ausnahmen finden Sie unter hier .

    Es gibt jedoch noch keine Garantie, dass GC nicht aufgerufen wird. Wenn Sie beispielsweise eine Bibliothek in "Kein GC-Regionscode" verwenden und diese Bibliothek GC.Collect () aufruft, wird nicht nur die Garbage Collection auftreten, sondern auch eine Ausnahme wird durch GC.EndNoGCRegion () ausgelöst.

    Ich befürchte, Sie müssen Ihre Herangehensweise überdenken, da die .NET-Garbage Collection (ab .NET 4.6) offenbar nicht für die Verarbeitung von Millionen zugeordneter Objekte mit komplexen Beziehungen zwischen ihnen erstellt wurde. Die NFX-Bibliothek, die in einem der Beiträge erwähnt wird, ist sowohl eine Option als auch die Verwendung von Strukturen, die Vereinfachung des Modells zur Verringerung der Beziehungen, die Verwendung von Indizes in Arrays anstelle von Referenzen usw.

    09 October 2015
    Slobodan Savkovic
  • Wir hatten ein ähnliches Problem mit dem Zwischenspeichern von Social + Routing-Daten. Wir mussten Hunderte von Millionen von Einträgen zwischenspeichern, da das Speichern dieses Out-of-Process-Vorgangs aufgrund des Netzwerkverkehrs (selbst im lokalen Netzwerk) nicht schnell genug war host). Stattdessen haben wir einen speziellen 100% verwalteten Speichermanager erstellt, der Byte [] -Segmente und die Unterzuordnungen den Platz dort zuordnet. Die Objekte aus dem CLR-Heap werden durch eine spezielle binäre Serialisierung in "PilePointers {int segment, int address}" umgewandelt, die um Größenordnungen schneller als BinaryFormatter ist. So kann nun der Objektgraph beliebiger Komplexität und Größe für eine LOMG TIME im verwalteten Heap gespeichert werden, die GC-Blockierungspause & lt; 10 ms, der volle GC-Wert liegt bei 30-60 ms.

    Wir speichern 300.000.000 Objekte problemlos auf einem 64-GB-PC und der interessanteste Teil davon ist this: Die Lösung funktioniert WAS SCHNELLER als das Speichern von Objekten in einem nicht verwalteten Haufen über Marshal oder Out-of-Process über redis / memcache.

    Siehe Dies: Pile: https://www.youtube.com/watch?v = IUBF2Ncvbbs

    Cache: https://www.youtube.com/watch?v=Dz_7hukyejQ

    Code abrufen (Apache 2): https://github.com/aumcode/nfx

    13 May 2015
    itadapter DKh
  • Nein.

    Sie können es nicht unterdrücken, da es notwendig ist, die Garantie zu gewährleisten Programm (zumindest in Bezug auf das Framework).

    Einfach ausgedrückt: Die CLR lässt Sie nicht so gefährlich leben. Wenn Sie eine manuelle Speicherverwaltung benötigen, müssen Sie Ihre eigenen Datenstrukturen aus struct erstellen und alles manuell verwalten.


    25 Millionen sind zwar viele Objekte, sollten aber nicht mehrere Gigabyte groß sein, es sei denn, Ihre Objekte sind auch relativ groß. Können Sie Arrays von Strukturen anstelle von Klassen verwenden, um zusätzliche Verweise zu vermeiden? Gibt es Informationen, die Sie entfernen können?

    22 November 2011
    Mehrdad