Ich habe eine Hochleistungsanwendung, die eine sehr große Datenmenge verarbeitet. Es empfängt, analysiert und verwirft enorme Informationsmengen in sehr kurzen Zeiträumen. Dies führt zu einer beträchtlichen Menge an Objektabwanderung, die ich derzeit zu optimieren versuche, verursacht jedoch auch ein sekundäres Problem. Wenn die Garbage Collection aktiviert wird, kann dies zu langen Verzögerungen beim Aufräumen führen (mit 10 meine ich 10 bis 100 Millisekunden). In 99% der Fälle ist dies akzeptabel, aber für kurze Zeitfenster von etwa 1 bis 2 Minuten muss ich absolut sicher sein, dass die Speicherbereinigung keine Verzögerung verursacht. Ich weiß, wann diese Zeiträume im Voraus auftreten werden, und ich muss nur sicherstellen, dass die Speicherbereinigung in diesem Zeitraum nicht erfolgt. Die Anwendung wird mit .NET 4 in C # geschrieben.
Meine Fragen sind;
- Ist es möglich, die Garbage Collection für das gesamte Programm kurz anzuhalten?
- Ist es möglich, mit System.GC.Collect () die Speicherbereinigung vor dem Fenster zu erzwingen, das ich für die Speicherbereinigung benötige, und wenn ja, wie lange bin ich für die Speicherbereinigung frei?
- Welchen Rat haben die Menschen, um den Bedarf an Garbage Collection insgesamt zu minimieren?
Hinweis - Dieses System ist ziemlich komplex mit vielen verschiedenen Komponenten. Ich hoffe, dass ich nicht zu einem Ansatz übergehen muss, bei dem ich für jede Klasse des Programms eine benutzerdefinierte IDisposable-Schnittstelle implementieren muss.
quelle
IDisposable
Implementierung für jede Klasse zur Lösung Ihres Problems beitragen? Diese Objekte müssten nach der Entsorgung noch GC-geprüft werden, nicht wahr?IDisposable
hat nichts mit Garbage Collection zu tun.Antworten:
.NET 4.6 hat zwei neue Methoden hinzugefügt:
GC.TryStartNoGCRegion
undGC.EndNoGCRegion
nur dafür.quelle
GCLatencyMode oldMode = GCSettings.LatencyMode; // Make sure we can always go to the catch block, // so we can set the latency mode back to `oldMode` RuntimeHelpers.PrepareConstrainedRegions(); try { GCSettings.LatencyMode = GCLatencyMode.LowLatency; // Generation 2 garbage collection is now // deferred, except in extremely low-memory situations } finally { // ALWAYS set the latency mode back GCSettings.LatencyMode = oldMode; }
Auf diese Weise können Sie den GC so weit wie möglich deaktivieren. Es werden keine großen Sammlungen von Objekten erstellt, bis:
GC.Collect()
GCSettings.LatencyMode
auf etwas anderes alsLowLatency
Bitte seien Sie dabei vorsichtig, da die Speichernutzung in diesem
try
Block extrem schnell ansteigen kann . Wenn der GC sammelt, geschieht dies aus einem bestimmten Grund, und Sie sollten dies nur ernsthaft in Betracht ziehen, wenn Sie über eine große Menge an Speicher auf Ihrem System verfügen.In Bezug auf Frage drei können Sie möglicherweise versuchen, Objekte wie Byte-Arrays wiederzuverwenden, wenn Sie Informationen über Dateisystem-E / A oder ein Netzwerk empfangen. Wenn Sie diese Informationen in benutzerdefinierte Klassen zerlegen, versuchen Sie auch, diese wiederzuverwenden, aber ich kann nicht zu viele gute Ratschläge geben, ohne mehr darüber zu wissen, was genau Sie tun.
Hier sind einige MSDN-Artikel, die ebenfalls helfen können:
PrepareConstrainedRegions()
)Hinweis:
GCSettings.LatencyMode = GCLatencyMode.LowLatency
kann nur eingestellt werden, wennGCSettings.IsServerGC == false
.IsServerGC
kann geändert werden inApp.config
:<runtime> <gcServer enabled="false" /> </runtime>
quelle
LowLatency
bis die Nachricht eintrifft. Länger als das, und ich würde sagen, dass Sie meines Wissens nicht viel tun können. Wenn Sie unbedingt keine GC-Verzögerung haben müssen, können Sie versuchen, die Sendung in einem anderen Prozess zu empfangen und sie dann auf Ihren Hauptprozess zu übertragen. Dies erschwert die Sache jedoch erheblich. Für 2 ist die Eingabe einer CER meines Erachtens mit einem Leistungseinbruch verbunden, wenn Sie sie betreten und verlassen, aber ich habe sie nie gemessen oder den Latenzmodus selbst eingestellt.