C # Erhöhen Sie die Heap-Größe - ist es möglich

8

Ich habe eine Ausnahme wegen zu wenig Speicher beim Verwenden von C # beim Einlesen einer massiven Datei

Ich muss den Code ändern, aber vorläufig kann ich die Größe des Heapspeichers (wie in Java) als Shaort-Term-Fix erhöhen?

    
Jack Kada 24.02.2010, 10:55
quelle

5 Antworten

6

.Net macht das automatisch.

Sieht so aus, als ob Sie die Grenze des Speichers erreicht haben, den ein .Net-Prozess für seine Objekte verwenden kann (auf 32-Bit-Rechnern sind dies 2 Standard- oder 3 GB durch Verwendung des / 3GB-Boot-Schalters. Credits an Leppie & Eric Lippert für die Info).

Überdenken Sie Ihren Algorithmus, oder vielleicht hilft eine Änderung an einer 64-Bit-Maschine.

    
GvS 24.02.2010, 10:59
quelle
5

Nein, das ist nicht möglich. Dieses Problem kann auftreten, weil Sie auf einem 32-Bit-Betriebssystem ausgeführt werden und Arbeitsspeicher zu fragmentiert ist. Versuchen Sie nicht, die gesamte Datei in den Speicher zu laden (z. B. Zeile für Zeile) oder, wenn Sie sie wirklich vollständig laden müssen, indem Sie sie in mehrere kleinere Teile laden.

    
Steven 24.02.2010 11:00
quelle
2

Nein, Sie können meine Antwort hier nicht sehen: Gibt es eine Möglichkeit, den Heap in der .NET-Laufzeit vorzubelegen, wie -Xmx / -Xms in Java?

Zum Lesen großer Dateien ist es normalerweise vorzuziehen, sie von der Festplatte zu streamen, sie in Blöcken zu lesen und sie Stück für Stück zu bearbeiten, anstatt das Ganze von vorne zu laden.

    
Paolo 24.02.2010 11:01
quelle
2

Wie andere schon gesagt haben, ist dies nicht möglich. Die .NET-Laufzeit verarbeitet im Namen der Anwendung Heap-Zuordnungen.

Nach meiner Erfahrung leiden .NET-Anwendungen häufig unter OOM, wenn genügend Speicher zur Verfügung steht (oder zumindest so aussieht). Der Grund dafür ist in der Regel die Verwendung von großen Sammlungen wie Arrays, List (die ein Array verwendet, um ihre Daten zu speichern) oder ähnliches.

Das Problem ist, dass diese Typen manchmal Spitzen bei der Speicherbenutzung erzeugen. Wenn diese Spitzenanforderungen nicht eingehalten werden können, wird eine OOM-Ausnahme ausgelöst. Z.B. Wenn List seine Kapazität erhöhen muss, wird ein neues Array mit der doppelten aktuellen Größe zugewiesen und anschließend werden alle Referenzen / Werte von einem Array zum anderen kopiert. In ähnlicher Weise erstellt Operationen wie ToArray eine neue Kopie des Arrays. Ich habe auch ähnliche Probleme bei großen LINQ-Operationen gesehen.

Jedes Array wird als zusammenhängender Speicher gespeichert. Um OOM zu vermeiden, muss die Runtime daher einen großen Speicherblock erhalten können. Da der Adressraum des Prozesses aufgrund des DLL-Ladens und der allgemeinen Verwendung für den Heap fragmentiert werden kann, ist dies nicht immer möglich. In diesem Fall wird eine OOM-Ausnahme ausgelöst.

    
Brian Rasmussen 24.02.2010 11:24
quelle
0

Um welche Art von Datei handelt es sich?

Sie könnten besser mit einem StreamReader arbeiten und die Rückgabe des ReadLine-Ergebnisses liefern, wenn es sich um einen Text handelt.

Sicher, Sie werden einen Dateizeiger herumtragen, aber das Worst-Case-Szenario wird massiv reduziert.

Es gibt ähnliche Methoden für Binärdateien. Wenn Sie beispielsweise eine Datei nach SQL hochladen, können Sie ein Byte [] lesen und die Sql Pointer-Mechanik verwenden, um den Puffer an das Ende eines Blobs zu schreiben.

    
Russ Clarke 24.02.2010 11:31
quelle

Tags und Links