Problembehandlung bei Problemen mit nicht genügend Arbeitsspeicher (System.OutOfMemoryException) in ASP.NET
Dieser Artikel hilft Ihnen bei der Problembehandlung bei Fehlern bei nicht genügend Arbeitsspeicher in ASP.NET.
Ursprüngliche Produktversion: ASP.NET
Ursprüngliche KB-Nummer: 2020006
Problembeschreibung
Eines der häufigsten Probleme, das wir in Microsoft-Kundensupportdiensten sehen, sind OutOfMemoryException Szenarien. Wir haben also eine Sammlung von Ressourcen zusammengestellt, um die Problembehandlung und Identifizierung der Ursache von Speicherproblemen zu unterstützen.
Bevor wir uns mit den Details der Problembehandlung OutOfMemoryException befassen, ist es wichtig zu verstehen, was dieses Problem verursacht. Im Gegensatz zu dem, was viele Entwickler glauben, wirkt sich die menge des installierten RAM nicht auf die Möglichkeit einer OutOfMemoryException . Ein 32-Bit-Betriebssystem kann 4 GB virtuellen Adressraum adressiert, unabhängig von der Menge des physischen Speichers, der im Feld installiert ist. Davon sind 2 GB für das Betriebssystem reserviert (Kernelmodusspeicher) und 2 GB für Benutzermodusprozesse. Die für den Kernelmodusspeicher reservierten 2 GB werden für alle Prozesse freigegeben, aber jeder Prozess erhält seine eigenen 2 GB Adressraum im Benutzermodus. Es wird davon ausgegangen, dass Sie nicht mit aktiviertem Switch ausgeführt /3gb werden.
Wenn eine Anwendung Arbeitsspeicher verwenden muss, reserviert sie einen Block des virtuellen Adressraums und übergibt dann Speicher aus diesem Block. Dies ist genau das, was der Garbage Collector (GC) des .NET Framework tut, wenn er Arbeitsspeicher benötigt, um die verwalteten Heaps zu vergrößern. Wenn der GC ein neues Segment für den kleinen Objekt-Heap benötigt (in dem sich Objekte kleiner als 85 KB befinden), werden 64 MB zugewiesen. Wenn ein neues Segment für den Heap für große Objekte benötigt wird, werden 16 MB zugewiesen. Diese umfangreichen Zuordnungen müssen aus zusammenhängenden Blöcken des Adressraums von 2 GB erfüllt werden, mit denen der Prozess arbeiten muss. Wenn das Betriebssystem die Anforderung des GC nach einem zusammenhängenden Speicherblock nicht erfüllen kann, tritt ein System.OutOfMemoryException OoM (OoM) auf.
Hinweis
Ein 32-Bit-Prozess, der auf einem 64-Bit-Betriebssystem ausgeführt wird, kann 4 GB Benutzermodusspeicher adressieren, und ein 64-Bit-Prozess, der auf einem 64-Bit-Betriebssystem ausgeführt wird, kann 8 TB Arbeitsspeicher im Benutzermodus adressieren, sodass eine OoM auf einem 64-Bit-Betriebssystem wahrscheinlich nicht möglich ist. Es ist möglich, ein OOM in einem 32-Bit-Prozess zu erleben, der auf einem 64-Bit-Betriebssystem ausgeführt wird, aber in der Regel tritt es erst auf, wenn der Prozess fast 3 GB private Bytes verwendet.
Es gibt zwei Gründe, warum möglicherweise eine OOM-Bedingung angezeigt wird.
- Ihr Prozess verwendet viel Arbeitsspeicher (in der Regel über 800 MB in einer 32-Bit-Umgebung).
- Der virtuelle Adressraum ist fragmentiert, wodurch die Wahrscheinlichkeit reduziert wird, dass eine große, zusammenhängende Zuordnung erfolgreich ist.
Es ist auch möglich, eine OOM-Bedingung aufgrund einer Kombination aus 1 und 2 zu sehen. Weitere Informationen finden Sie unter Problembehandlung von System.OutOfMemoryExceptions in ASP.NET.
Wenn eine Windows-Willkommensseite auftritt, werden Sie möglicherweise eines oder mehrere der folgenden Symptome bemerken:
Ihre Anwendung stürzt ab. Weitere Informationen finden Sie unter Wer ist dieser OutOfMemory-Computer und warum stürzt er meinen Prozess ab, wenn ich viel Arbeitsspeicher übrig habe?.
Ihre Anwendung kann, wie durch den Task-Manager oder den Leistungsmonitor angegeben, über hohen Arbeitsspeicher verfügen.
Die Verarbeitung von Anforderungen kann sehr viel Zeit in Anspruch nehmen.
In Internetinformationsdienste (IIS) 7 können Sie problembehandlungsfehlerbehebungsanforderungen mithilfe der Ablaufverfolgung in IIS 7 verwenden, um lange ausgeführte Anforderungen zu behandeln.
Benutzer können aufgrund der Windows-Willkommensseite eine Fehlermeldung in der Anwendung melden.
Wenn es darum geht, die Ursache für eine OOM-Bedingung zu ermitteln, arbeiten Sie tatsächlich daran, die Ursache für eine hohe Speichersituation oder ein fragmentiertes Adressraum zu ermitteln. Obwohl wir nicht alle möglichen Ursachen für diese Situationen dokumentieren können, gibt es einige häufige Ursachen, die wir regelmäßig sehen.
In den folgenden Informationen werden die häufigsten Ursachen von OOM-Bedingungen und die Auflösungen für jede dieser Ursachen beschrieben.
Zeichenfolgenverknüpfung
Zeichenfolgen in einer verwalteten Anwendung (eine Anwendung, die mithilfe des .NET Framework geschrieben wurde) sind unveränderlich. Wenn einer Zeichenfolge ein neuer Wert zugewiesen wird, wird eine Kopie der vorhandenen Zeichenfolge erstellt. Und der neue Wert wird der neuen Zeichenfolge zugewiesen. Es verursacht in der Regel keine Probleme. Wenn jedoch eine große Anzahl von Zeichenfolgen verkettet wird, führt dies zu viel mehr Zeichenfolgenzuweisungen, als ein Entwickler möglicherweise erkennt. Und dies kann zu Speicher- und OOM-Bedingungen führen.
Um OOM aufgrund einer Zeichenfolgenverkettung zu vermeiden, stellen Sie sicher, dass Sie die StringBuilder Klasse verwenden. Weitere Informationen finden Sie unter So verbessern Sie die Leistung bei der Zeichenfolgenverkettung in Visual C#.
Fragmentierung im verwalteten Heap
Der Garbage Collector (GC) in einer verwalteten Anwendung komprimiert die Heaps, um die Fragmentierung zu verringern. Es ist jedoch möglich, Objekte in einer verwalteten Anwendung zu anheften. Angeheftete Objekte können während der Heap-Komprimierung nicht verschoben werden. Dadurch würde die Adresse geändert, unter der sich das Objekt befindet. Wenn eine Anwendung eine große Anzahl von Objekten anheftet und/oder lange Objekte anheftet, kann dies zu Fragmentierung im verwalteten Heap führen. Dies kann dazu führen, dass der gc den verwalteten Heap häufiger vergrößert und eine OOM-Bedingung verursacht.
Wir haben seit der .NET Framework 1.0 an der Minimierung von OOM-Bedingungen aufgrund des Anheftens gearbeitet. In jeder Version wurden inkrementelle Verbesserungen vorgenommen. Es gibt jedoch weiterhin Entwurfsmuster, die Sie implementieren können, die von Vorteil sind, wenn Sie Objekte anheften müssen.
Fragmentierung im Virtual Address (VA)-Raum
Jedem Prozess ist eine bestimmte Menge Arbeitsspeicher zugeordnet, und dieser Speicher stellt den VA-Speicherplatz für den Prozess dar. Wenn der VA-Raum fragmentiert wird, erhöht dies die Wahrscheinlichkeit, dass der GC keinen großen Block zusammenhängenden Speichers erhalten kann, um die verwalteten Heaps zu vergrößern. Und dies kann zu einer OOM-Bedingung führen.
Die Fragmentierung im VA-Raum wird häufig durch eines oder mehrere der folgenden Szenarien verursacht:
Laden derselben Assemblys in mehrere Anwendungsdomänen.
Wenn Sie eine Assembly in mehr als einer Anwendung verwenden müssen, die im selben Anwendungspool ausgeführt wird, benennen Sie die Assembly mit starkem Namen, und installieren Sie sie im GAC. Dadurch stellen Sie sicher, dass die Assembly nur einmal in den Prozess geladen wird.
Ausführen einer Anwendung in der Produktion mit dem Debugattribut des
<compilation>Elements auftrue.- Das Debugattribut des
<compilation>Elements sollte sich in der Produktionfalsebefindet. - Sie können die
<deploy retail="true" />Konfiguration verwenden, um sicherzustellen, dass das Debuggen im Produkt immer deaktiviert ist. Weitere Informationen finden Sie unter deployment Element (ASP.NET Einstellungen Schema).
- Das Debugattribut des
Verwendung von Skripts in XSL-Transformationen (eXtensible Style sheet Language) oder Erstellen
XmlSerializersvon .In diesem Fall dynamische Assemblys, die durch XSLT-Skripts (Extensible Style sheet Language Transformations) oder verursacht
XmlSerializerswerden.
Zurückgeben großer Datensätze
Bei der Verwendung von Daten aus einer Datenbank oder einer anderen Datenquelle ist es wichtig, die zurückgegebene Datenmenge einzuschränken. Beispielsweise ist das Zwischenspeichern eines Abfrageergebnisses, das eine gesamte Datenbanktabelle zurückgibt, um die Kosten für das Abrufen von Datenteilen aus der Datenbank bei Bedarf zu vermeiden, kein guter Ansatz. Dies kann leicht zu hohem Speicher führen und zu einer OOM-Bedingung führen. Ein Benutzer kann eine ähnliche Abfrage starten, ist eine weitere gängige Methode, um eine hohe Speichersituation zu erstellen. Geben Sie beispielsweise alle Mitarbeiter in einem Unternehmen oder alle Kunden im Us-Bundesstaat Texas mit einem Nachnamen zurück, der mit dem Buchstaben S beginnt.
Beschränken Sie immer die Datenmenge, die von einer Datenbank zurückgegeben werden kann. Lassen Sie keine Abfragen zu, z. SELECT * FROM. . . B. weil Sie dann keine Kontrolle darüber haben, wie viele Daten auf Ihrer Seite angezeigt werden.
Es ist ebenso wichtig sicherzustellen, dass Sie in UI-Elementen, z. B. dem GridView-Steuerelement, kein großes Datenergebnis anzeigen. Neben dem für die zurückgegebenen Daten erforderlichen Arbeitsspeicher verbrauchen Sie auch große Datenmengen in Zeichenfolgen und in UI-Elementen, die zum Rendern der Ergebnisse erforderlich sind. Durch Implementieren von Paging und Überprüfen von Eingaben, sodass keine großen Datensätze zurückgegeben werden, können Sie dieses Problem vermeiden.
Ausführung in einer Produktionsumgebung mit aktivierter Ablaufverfolgung
ASP.NET Ablaufverfolgung ist ein leistungsstarkes Feature für die Problembehandlung von Anwendungen. In einer Produktionsumgebung sollte es jedoch nie weitergelassen werden. ASP.NET Ablaufverfolgung Datenstrukturen verwendet, z. B. zum Speichern von DataTables Ablaufverfolgungsinformationen, und im Laufe der Zeit können sie eine hohe Speicherbedingung verursachen, die zu OOM führen kann.
Die Ablaufverfolgung sollte in einer Produktionsumgebung deaktiviert werden. Sie können dies tun, indem Sie das enabled Attribut des Elements in Der <trace> web.config Datei auf "false" festlegen. Durch Aktivieren der Einzelhandelsbereitstellung mithilfe der <deploy retail="true" /> Ablaufverfolgung wird auch die Ablaufverfolgung in Ihren Anwendungen deaktiviert.
Systemeigene Ressourcenlecks
Viele verwaltete Ressourcen verwenden auch systemeigene Ressourcen. Da der GC systemeigene Ressourcen nicht bereinigt, ist ein Entwickler für die Implementierung und den Aufruf der Dispose-Methode zum Bereinigen systemeigener Ressourcen verantwortlich. Wenn Sie einen Typ verwenden, der die IDisposable Schnittstelle implementiert, und Sie die Methode nicht aufrufen, besteht das Risiko, dass Dispose systemeigene Ressourcen offengelegt werden und eine OOM-Bedingung verursacht wird.
Diese Objekte sollten die iDisposable Schnittstelle implementieren, und Sie sollten die Dispose Methode für diese Objekte aufrufen, wenn Sie sie nicht mehr benötigen.