如何在.NET中序列化大对象? (OutOfMemory Exceptions)

时间:2009-04-02 11:55:35

标签: .net memory serialization out-of-memory

我在我的应用程序中使用序列化来“保存”功能。但是当数据太大(15+ MB)时,我开始出现OutOfMemory异常。

我有很多对象,并且它们与其他小物体相连,我认为这会导致处理能力和内存中的数据过多。

我的代码基于此,几乎相同:

http://www.codeproject.com/KB/vb/TreeViewDataAccess.aspx

修改:

  1. 我不使用自定义序列化,它全部由[序列化]属性完成。不包括某些字段。

  2. 我序列化了很多对象和自定义类。包括字典,结构和其他一些东西。

  3. 我将其序列化为一个文件。

  4. 我使用的是XmlSerializer

  5. P.S。我有4 GB的物理内存。

    解决方案

    感谢答案,我发现我的问题是XmlSerializer,我已经摆脱它了。二进制序列化可以很好地处理我得到的数据。

7 个答案:

答案 0 :(得分:3)

我有完全相同的问题。原因是.NET 序列化不会扩展。

我用Simon Hewitt的优秀开放解决了这个问题 源库,请参阅 Optimizing Serialization in .NET - part 2

除了大幅减少内存使用量外,它还有很多 快点。与文章类似,我加速了20次。

答案 1 :(得分:2)

实际上,XmlSerializer忽略了SerializableAttribute属性。它们仅由格式化类(BinaryFormatter,SoapFormatter)使用。

我不会使用XmlSerializer序列化,尤其不是XmlSerializer和BinaryFormatter的组合。

我只想尝试使用BinaryFormatter序列化所有内容。

答案 2 :(得分:1)

15MB不应该给你一个OOM。

如果数据是树状的(而不是完整的图形),您可能会考虑像protobuf-net这样的序列化器;除了使用Google非常高效(速度和内存)二进制“协议缓冲”格式之外,它还可以从不必执行参考跟踪(图形所需) - 这意味着它只需要担心数据一次(如果它有两次)得到缓冲)。

但是,这需要对您的类进行不同的标记(或者至少需要“选择加入”) - 并且它不会处理完整的图形。但它就在那里,并且免费......

答案 3 :(得分:0)

您可以编写自己的序列化例程,看看是否可以通过手工定制序列化过程获得任何性能优势。有关详细信息,请参阅MSDN page on Custom Serialization

答案 4 :(得分:0)

也许您可以向我们提供有关如何进行序列化的更多详细信息。你使用自定义序列化吗?或者你只是使用内置的[序列化]属性?

我认为处理这个问题的一个好方法是尝试执行自定义序列化逻辑并仅仅序列化您需要的内容,它不能达到4GB,无论如何它还取决于您的应用程序有多少内存。分配

答案 5 :(得分:0)

使用此处提到的所有方法,丢失了将大对象转储到磁盘和恢复的难易程度。此外,这些只支持转储数据类型,因此您无法像使用BinaryFormatter一样轻松地转储引用类型。

在大型对象的二进制格式化之前,使用gzip7-Zip进行压缩实际上会将大小超过16 MB的大小移动到32 MB之类。

答案 6 :(得分:0)

您可以下载JSON.NET在我的项目中工作的库超过100 MB数据的序列化和反序列化。

对于序列化,您可以像

一样工作

如果你有Object使用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);
  }

这可能适合你。