我有大量对象需要稍后存储和检索。该列表将始终用作一个单元,并且不会单独检索列表项。该列表包含大约 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)
在线上。
因此,我尝试使用不同的协议,Protocol Buffers。我尝试使用 Nuget 包 protobuf-net 和 Google.Protobuf 中的两种实现,但是序列化速度非常慢(大约 30 分钟),而且根据我的阅读,Protobuf 没有针对序列化大于 1MB 的数据进行优化。所以,我回到绘图板上,遇到了 Cap'n Proto,它承诺通过使用内存映射来解决我的速度问题。我正在尝试使用 @marc-gravell 的 C# 绑定,但我在实现序列化程序时遇到了一些困难,因为该项目还没有完整的文档。此外,我不能 100% 确定 Cap'n Proto 是协议的正确选择 - 但我正在努力在网上找到任何替代建议。
如何以相当快的方式将非常大的项目集合序列化到 blob 存储,而不会遇到内存问题?