2016-04-07 14 views
4

Ich habe eine große Liste von Objekten, die ich später speichern und abrufen muss. Die Liste wird immer als eine Einheit verwendet und Listenelemente werden nicht einzeln abgerufen. Die Liste enthält etwa 7000 Artikel mit insgesamt etwa 1 GB, könnte aber leicht auf das Zehnfache oder mehr eskalieren.Serialisierung einer sehr großen Liste von Elementen in Azure-Blobspeicher mit C#

Wir haben BinaryFormatter.Serialize() verwendet, um die Serialisierung durchzuführen (System.Runtime.Serialization.Formatters.Binary.BinaryFormatter). Diese Zeichenfolge wurde dann als Blob in den Azure-Blobspeicher hochgeladen. Wir fanden es im Allgemeinen schnell und effizient, aber es wurde unzureichend, da wir es mit einer größeren Dateigröße testen und eine OutOfMemoryException werfen. Von dem, was ich verstehe, obwohl ich einen Stream verwende, ist mein Problem, dass die BinaryFormatter.Serialize() Methode zuerst alles in den Speicher serialisieren muss, bevor ich den Blob hochladen kann, was meine Ausnahme verursacht.

Die binäre Serializer sieht wie folgt aus:

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); 
    } 
} 

Die OutOfMemoryException tritt auf der formatter.Serialize(stream, value) Linie.

Ich versuchte daher, ein anderes Protokoll zu verwenden, Protocol Buffers. Ich habe versucht, beide Implementierungen in den Nuget-Paketen protobuf-net und Google.Protobuf zu verwenden, aber die Serialisierung war furchtbar langsam (ungefähr 30 Minuten) und nach dem, was ich gelesen habe, ist Protobuf nicht für das Serialisieren von Daten größer als 1 MB optimiert. Also ging ich zurück zum Zeichenbrett und stieß auf Cap'n Proto, der versprochen hatte, meine Geschwindigkeitsprobleme durch Speichermapping zu lösen. Ich versuche, die @ C-Bindungen von @ marc-gavell zu verwenden, aber ich habe Schwierigkeiten, einen Serialisierer zu implementieren, da das Projekt noch keine gründliche Dokumentation hat. Außerdem bin ich mir nicht 100% ig sicher, dass Cap'n Proto die richtige Protokollwahl ist - aber ich habe Mühe, alternative Vorschläge online zu finden.

Wie kann ich eine sehr große Sammlung von Objekten in Blob-Speicher serialisieren, ohne Speicherprobleme zu bekommen, und auf eine relativ schnelle Weise?

+0

Hochladen Chargen mehr als ein Klecks Serialize arbeiten, als auf einmal alles Serialisierung? – spender

+0

Danke, das ist eine Option, über die ich nachdenke. Jede Liste ist bereits ein Brocken in unserer Domain, also würden die Blobs den Kontext etwas verlieren und es würde die Angelegenheit etwas komplizierter machen. Guter Vorschlag, aber ich werde es versuchen, wenn es keine anderen Protokoll- oder Methodenvorschläge gibt. – Ivan

Antwort

0

Vielleicht sollten Sie zu JSON wechseln?

Mithilfe des JSON-Serializers können Sie zu und von Dateien streamen und die Datei seriell/deserialisieren (wenn die Datei gelesen wird).

Würden Ihre Objekte gut auf JSON abgebildet?

Das ist, was ich verwende, um einen NetworkStream zu nehmen und in ein Json-Objekt zu legen.

Darüber hinaus können Sie den Stream GZip, um die Dateiübertragungszeiten zu reduzieren. Wir streamen direkt zu GZipped JSON und wieder zurück.

bearbeiten, obwohl dies ein Deserialize ist, sollte der gleiche Ansatz für ein eher