Frage

Ich habe 10 Fäden Tausende von kleinen Puffern (16-30 Bytes jeweils) zu einer großen Datei in zufälligen Positionen zu schreiben. Einige der Themen werfen OutOfMemoryException auf FileStream.Write () opreation.

Was ist die Ursache der OutOfMemoryException? Was es zu sehen?

Ich bin das Filestream wie folgt aus (für jeden geschriebenen Artikel - dieser Code ausgeführt wird aus 10 verschiedenen Themen):

using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, BigBufferSizeInBytes, FileOptions.SequentialScan))
{
 ...
 fs.Write();
}

Ich vermute, dass alle Puffer innerhalb des Filestream zugeordnet nicht durch die GC in der Zeit frei bekommen. Was ich nicht verstehe ist, warum die CLR, anstelle des Werfens, läuft nicht nur einen GC-Zyklus und frei bis alle nicht verwendeten Puffer?

Keine korrekte Lösung

Andere Tipps

Wenn zehn Threads Öffnen von Dateien als Code zeigt, dann haben Sie maximal zehn undisposed Filestream-Objekte zu einem beliebigen Zeitpunkt. Ja, Filestream hat hat einen internen Puffer, die Größe, die Sie mit „BigBufferSizeInBytes“ im Code angeben. Könnten Sie bitte den genauen Wert offen legen? Wenn diese groß genug ist (z ~ 100 MB), dann könnte es auch die Ursache des Problems sein.

In der Standardeinstellung (das heißt, wenn Sie keine Nummer auf Konstruktion angeben), ist dieser Puffer 4 KB und das ist in der Regel gut für die meisten Anwendungen. Im Allgemeinen, wenn Sie wirklich über Plattenschreibleistung kümmern, dann könnten Sie diese ein, um ein paar 100kB erhöhen, aber nicht mehr.

Doch für Ihre spezifische Anwendung tun würde so nicht viel Sinn machen, da der Puffer wird nie mehr enthalten als die 16-30 Bytes, die Sie in sie schreiben, bevor Sie das Objekt Filestream Entsorgen ().

Um Ihre Frage zu beantworten, wird ein OutOfMemoryException nur ausgelöst, wenn der angeforderte Speicher nicht zugeordnet werden kann, nach ein GC ausgeführt wird. Noch einmal, wenn der Puffer wirklich groß ist, dann könnte das System viele Speicher halten kann, nur nicht ein zusammenhängende Brocken. Dies liegt daran, das große Objektheap nie verdichtet wird.

Es ist möglich, dass diese Einschränkungen aus dem zugrunde liegenden Betriebssystem auftreten, und dass das .NET Framework ist machtlos, diese Art von Einschränkungen zu überwinden.

Was kann ich nicht aus dem Code Probe ableiten, ob Sie eine Menge dieser Objekte Filestream zur gleichen Zeit öffnen, oder öffnen Sie sie wirklich schnell nacheinander. Ihre Nutzung des ‚mit‘ Schlüsselwort wird sicherstellen, dass die Dateien nach dem fs.Write () -Aufruf geschlossen sind. Es gibt keinen GC-Zyklus benötigt, um die Datei zu schließen.

Die Filestream-Klasse ist wirklich auf sequentiellen Lese- / Schreibzugriff auf Dateien ausgerichtet. Wenn Sie schnell an zufälligen Orten in einer großen Datei schreiben müssen, könnten Sie einen Blick auf mit virtueller Dateizuordnung nehmen.

Update: Es scheint, dass virtuelle Dateizuordnung nicht offiziell bis 4.0 in .NET unterstützt werden. Sie können einen Blick auf Dritte-Implementierungen für diese Funktionalität nehmen.

Dave

Ich erlebe etwas ähnliches und fragte sich, ob Sie überhaupt die Wurzel des Problems festgenagelt?

Mein Code funktioniert ziemlich viel Kopieren zwischen Dateien, ganz wenige megs zwischen verschiedenen Byte-Dateien übergeben. Ich habe bemerkt, dass, während die Prozess Speichernutzung in einem vernünftigen Rahmen bleibt, schießt die System Speicherzuweisung auf viel zu hoch während des Kopier - viel mehr als durch meinen Prozess verwendet wird.

ich das Problem verfolgt habe bis auf die FileStream.Write () -Aufruf - wenn diese Linie herausgenommen wird, scheint die Speichernutzung als erwartet zu gehen. Mein BigBufferSizeInBytes ist die Standardeinstellung (4k), und ich kann nicht überall sehen, wo diese zu sammeln könnten ...

Alles, was Sie während der Suche auf Ihrem Problem entdeckt dankbar empfangen würde!

scroll top