.NET でビッグ オブジェクトをシリアル化するにはどうすればよいですか?(メモリ不足例外)
-
22-08-2019 - |
質問
アプリケーションの「保存」機能にシリアル化を使用しています。しかし、データが大きすぎる場合 (15 MB 以上)、OutOfMemory 例外が発生し始めます。
非常に多くのオブジェクトがあり、それらは他の小さなオブジェクトと接続されているため、処理能力とメモリ内に保持されるデータが過剰になっていると思います。
私のコードはこれに基づいており、ほぼ同じです:
http://www.codeproject.com/KB/vb/TreeViewDataAccess.aspx
編集 :
カスタムシリアル化は使用しません。すべて [Serialization] 属性によって行われます。一部分野を除きます。
非常に多くのオブジェクトとカスタム クラスをシリアル化します。辞書、構造、その他多数のものが含まれています。
ファイルにシリアル化します。
XmlSerializerを使用します
追伸物理メモリは 4 GB あります。
解決
回答のおかげで、私の問題は XmlSerializer にあることが判明し、それを取り除くことができました。バイナリ シリアル化は、私が入手したデータでは問題なく機能しています。
解決
15メガバイトはあなたにOOMを与えるべきではありません。
データがツリー状(全体ではなくグラフ)である場合は、は、などのシリアライザを検討するかもしれませんいるProtobufネットの;だけでなく、Googleの(速度とメモリの両方)は非常に効率的なバイナリの「プロトコル・バッファー」形式を使用して、それが(グラフのために必要)追跡参照を行うには持っていないから利益を得る - それは持っている場合、それは二回しか(一度データを心配する必要があることを意味しますバッファリングを取得するために)。
しかし、これは(「オプトイン」、または少なくとも)あなたのクラスに異なるマークアップを要求する - そしてそれは完全なグラフを処理しません。しかし、それはそこにあり、無料...
他のヒント
私は正確に同じ問題を抱えていました。その理由は、.NETです 直列化はスケールしない。
私はサイモン・ヒューイットの優れたオープンを使用して問題を解決しました .NETでソースライブラリを参照してください。の最適化シリアル化 - パート 2 のの
劇的にメモリ使用量を削減するだけでなく、それもかなりあります もっと早く。記事と同様に、私は20倍のスピードアップを得ています。
実際には、XmlSerializerをはSerializableAttribute属性を無視します。彼らは唯一の書式設定のクラス(にBinaryFormatter、SoapFormatter)で使用しています。
私はXmlSerializerをとにBinaryFormatterの組み合わせをするXmlSerializerを使用してシリアライズし、特にはないではないでしょう。
私は単純にBinaryFormatterを使用して、すべてをシリアル化しようとするだろう。
あなたはあなた自身の直列化ルーチンを書いて、あなたは手で仕立て、あなたのシリアル化プロセスによってパフォーマンスの利点を得ることができるかどうかを確認できます。詳細については、/ <カスタム・シリアライズに MSDNのページをご覧ください>。
たぶん、あなたは私たちに直列化が行われている方法についてもう少し詳細を与えることができます。カスタムのシリアル化を使用していますか?それとも、ただ、組み込みの[シリアル化]属性を使用していますか?
私はあなたがこれを処理するための良い方法は、カスタムシリアル化のロジックを行い、必要なものだけを唯一のシリアル化しようとすることだと思い、それが4ギガバイトに行くことができない、とにかくそれはまた、アプリケーションが持っているどのくらいのmemeoryに依存します割り当てられています。
ここで言及されているすべてのアプローチでは、ディスクに大きなオブジェクトをダンプし、回復の容易さが失われています。また、これらのサポートは、データ型のみをダンプし、だから、同じように簡単にBinaryFormatterあなたが持つ可能性として参照型をダンプすることはできません。
// EN:また、 gzipののか<のhref = "HTTPを使用して圧縮を行います。ラージ・オブジェクトのバイナリフォーマットの前に「REL = 『nofollowをnoreferrer』> 7ジップの実際32メガバイトのように16メガバイト以上のサイズを移動wikipedia.org/wiki/7-Zip。
あなたは私のプロジェクトで働く JSON.NET のライブラリをダウンロードしてください可能性がより100メガバイトのデータのシリアライズとデシリアライズます。
シリアル化のためには、
のように動作することができますあなたが持っている場合は、オブジェクトを使用したTextWriter
using (TextWriter textWriter = File.CreateText("LocalJsonFile.json"))
{
var serializer = new JsonSerializer();
serializer.Serialize(textWriter , yourObject);
}
あなたが持っている場合は、文字列の使用にStringWriter
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using(JsonWriter textWriter = new JsonTextWriter(sw))
{
var serializer = new JsonSerializer();
serializer.Serialize(textWriter, yourObject);
}
これはあなたのために働くことがあります。