Meine Anwendung führt eine große Menge an binärer Serialisierung und Komprimierung großer Objekte durch. Unkomprimiert ist das serialisierte Dataset etwa 14 MB. Komprimiert ist es ca. 1,5 MB. Ich finde, dass, wenn ich die serialize-Methode auf meinem Dataset aufruft, mein großer Object-Heap-Leistungsindikator von unter 1 MB auf etwa 90 MB springt. Ich weiß auch, dass die Anwendung in einem relativ stark ausgelasteten System, gewöhnlich nach einer Laufzeit (Tage), in der dieser Serialisierungsprozess einige Zeit dauert, bekannt ist, Speicheraussetzungen zu verwerfen, wenn diese Serialisierungsmethode aufgerufen wird scheint viel Speicher zu sein. Ich vermute, dass die Fragmentierung das Problem ist (obwohl ich nicht sagen kann, ich bin 100% sicher, ich bin ziemlich nah)Soll ich GC.Collect sofort nach der Verwendung des Heapspeichers für große Objekte aufrufen, um Fragmentierung zu vermeiden
Die einfachste kurzfristige Lösung (ich denke, ich suche beide eine kurzfristige und eine langfristige Antwort) Ich kann daran denken, GC.Collect direkt nach dem Serialisierungsprozess zu nennen. Dies, meiner Meinung nach, wird Müll sammeln das Objekt aus der LOH und wird es wahrscheinlich VOR anderen Objekten hinzugefügt werden können. Dadurch können andere Objekte eng an die verbleibenden Objekte im Heap angepasst werden, ohne dass eine große Fragmentierung verursacht wird.
Anders als diese lächerliche 90MB Zuteilung glaube ich nicht, dass ich etwas anderes habe, das einen Verlust der LOH verwendet. Diese 90-MB-Zuweisung ist ebenfalls relativ selten (etwa alle 4 Stunden). Wir werden natürlich immer noch das 1,5-MB-Array dort und vielleicht einige andere kleinere serialisierte Objekte haben.
Irgendwelche Ideen?
-Update als Folge der guten Antworten
Hier ist mein Code, der die Arbeit macht. Ich habe tatsächlich versucht, dies zu ändern, um WHILE Serialisierung zu komprimieren, so dass die Serialisierung in einen Stream zur gleichen Zeit serialisiert und ich nicht viel besseres Ergebnis bekomme. Ich habe auch versucht, den Speicherstrom auf 100 MB vor zu reservieren und zu versuchen, denselben Strom zweimal hintereinander zu verwenden, der LOH geht sowieso auf 180 MB. Ich verwende Process Explorer, um es zu überwachen. Das ist verrückt. Ich denke, ich werde als nächstes die UnmanagedMemoryStream-Idee ausprobieren.
Ich würde Sie ermutigen, es auszuprobieren, wenn Sie nicht wollen. Es muss nicht genau dieser Code sein. Nur eine große Datenmenge serialisiert werden und Sie werden überraschende Ergebnisse erhalten (mir hat viele Tische, arround 15 und viele Strings und Spalten)
byte[] bytes;
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
serializer.Serialize(memStream, obj);
bytes = CompressionHelper.CompressBytes(memStream.ToArray());
memStream.Dispose();
return bytes;
Update nach binäre Serialisierung mit UnmanagedMemoryStream versucht
Auch wenn ich Serialize zu einem UnmanagedMemoryStream der LOH springt auf die gleiche Größe. Es scheint, dass, egal was ich tue, der BinaryFormatter genannt wird, um dieses große Objekt zu serialisieren, wird das LOH verwenden. Was die Vorausplanung betrifft, scheint es nicht viel zu helfen. Sagen wir, dass ich vorbeziehe, sag, dass ich 100MB vorbeile, dann serialisiere ich, es wird 170 MB verwenden. Hier ist der Code dafür. Noch einfacher ist als der obige Code
BinaryFormatter serializer = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream(1024*1024*100);
GC.Collect();
serializer.Serialize(memoryStream, assetDS);
Die GC.Collect() in der Mitte gibt es nur den LOH-Leistungsindikatoren zu aktualisieren. Sie werden sehen, dass die richtigen 100 MB zugewiesen werden. Aber dann, wenn Sie die Serialisierung aufrufen, werden Sie feststellen, dass dies zu den 100 hinzugefügt wird, die Sie bereits zugewiesen haben.
Gibt es etwas, was Sie tun können, um direkt zu einem 'Stream' zu serialisieren, anstatt die LOH als Puffer zu verwenden? –