5

後で保存して取得する必要があるオブジェクトのリストがたくさんあります。リストは常に 1 つの単位として使用され、リスト アイテムは個別に取得されません。リストには約 7000 個のアイテムが含まれており、合計で約 1 GB になりますが、簡単にその 10 倍以上にエスカレートする可能性があります。

BinaryFormatter.Serialize()シリアライゼーションを行うために使用しています( System.Runtime.Serialization.Formatters.Binary.BinaryFormatter)。次に、この文字列が BLOB として Azure BLOB ストレージにアップロードされました。一般的に高速で効率的であることがわかりましたが、より大きなファイル サイズでテストしてOutOfMemoryException. 私が理解していることから、私はストリームを使用していますが、私の問題はBinaryFormatter.Serialize()、ブロブをアップロードする前に、メソッドが最初にすべてをメモリにシリアル化する必要があり、例外が発生することです。

バイナリ シリアライザーは次のようになります。

public void Upload(object value, string blobName, bool replaceExisting)
{
    CloudBlockBlob blockBlob = BlobContainer.GetBlockBlobReference(blobName);
    var formatter = new BinaryFormatter()
    {
        AssemblyFormat = FormatterAssemblyStyle.Simple,
        FilterLevel = TypeFilterLevel.Low,
        TypeFormat = FormatterTypeStyle.TypesAlways
    };

    using (var stream = blockBlob.OpenWrite())
    {
        formatter.Serialize(stream, value);
    }
}

行で OutOfMemoryException が発生しformatter.Serialize(stream, value)ます。

したがって、別のプロトコルである Protocol Buffers を使用しようとしました。Nuget パッケージの protobuf-net と Google.Protobuf の両方の実装を使用してみましたが、シリアル化は恐ろしく遅く (約 30 分)、私が読んだところによると、Protobuf は 1 MB を超えるデータのシリアル化には最適化されていません。それで、私は製図板に戻って、Cap'n Proto に出会いました。Cap'n Proto は、メモリ マッピングを使用して速度の問題を解決すると約束しました。@marc-gravell の C# バインディングを使用しようとしていますが、プロジェクトにはまだ完全なドキュメントがないため、シリアライザーの実装に問題があります。さらに、Cap'n Proto がプロトコルの正しい選択であると 100% 確信しているわけではありませんが、オンラインで代替案を見つけるのに苦労しています.

非常に大規模なアイテムのコレクションを、メモリの問題を発生させることなく、かなり高速な方法で BLOB ストレージにシリアル化するにはどうすればよいですか?

4

2 に答える 2