使用C#将非常大的项列表序列化到Azure blob存储中
我有一个很大的对象列表,我需要在以后存储和检索.该列表将始终用作单位,并且不会单独检索列表项.该列表包含大约7000个项目,总计大约1GB,但可以轻松升级到那个或更多的十倍.
我们一直在使用BinaryFormatter.Serialize()来进行序列化(System.Runtime.Serialization.Formatters.Binary.BinaryFormatter).然后,此字符串作为blob上载到Azure blob存储.我们发现它通常是快速和有效的,但它变得不充分,因为我们用更大的文件大小测试它,抛出OutOfMemoryException.根据我的理解,虽然我正在使用流,但我的问题是BinaryFormatter.Serialize()方法必须首先将所有内容序列化为内存,然后才能上传blob,从而导致异常. 二进制序列化程序如下所示: 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)行上. 因此,我试图使用不同的协议,协议缓冲区.我尝试使用Nuget包protobuf-net和Google.Protobuf中的两种实现,但是序列化速度非常慢(大约30分钟),而且根据我的阅读,Protobuf没有针对大于1MB的序列化数据进行优化.所以,我回到绘图板,遇到了Cap’n Proto,它承诺通过使用内存映射来解决我的速度问题.我正在尝试使用@ marc-gravell的C#绑定,但是我在实现序列化程序时遇到了一些困难,因为该项目还没有完整的文档.此外,我不是100%确定Cap’n Proto是正确的协议选择 – 但我很难在网上找到任何其他建议. 如何将大量项目序列化为blob存储,而不会遇到内存问题,并且速度相当快? 解决方法
也许你应该切换到JSON?
使用JSON Serializer,您可以流式传输文件并从文件串行化/反序列化(随着文件的读取). 你的对象会映射到JSON吗? 这是我用来获取NetworkStream并放入Json对象的方法. private static async Task<JObject> ProcessJsonResponse(HttpResponseMessage response) { // Open the stream the stream from the network using (var s = await ProcessResponseStream(response).ConfigureAwait(false)) { using (var sr = new StreamReader(s)) { using (var reader = new JsonTextReader(sr)) { var serializer = new JsonSerializer {DateParseHandling = DateParseHandling.None}; return serializer.Deserialize<JObject>(reader); } } } } 此外,您可以GZip流以减少文件传输时间.我们直接流式传输到GZipped JSON并再次返回. 编辑,虽然这是反序列化,但同样的方法应该适用于序列化 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |