【问题标题】:Why is BinaryFormatter trying to serialize too much data?为什么 BinaryFormatter 试图序列化太多数据?
【发布时间】:2015-03-19 21:51:13
【问题描述】:

这个问题是SerializationException when serializing lots of objects in .NET 的后续问题。

情况:我有一个节点网络,这些节点都是相互连接的,每个节点可能有 10-30 个变量和/或引用。该网络大约有 900 万个条目,但我已经裁剪了 11,000 个条目的一部分,并切断了指向网络其余部分的引用。

我正在尝试将这部分网络写入磁盘,但出现以下错误:

System.Runtime.Serialization.SerializationException
"The internal array cannot expand to greater than Int32.MaxValue elements."

注意:正如stuartd 所指出的,可以序列化的项目数量限制为6 million

最可能的原因是我不知道与其他网络的连接仍然存在,但是我已经非常详细地搜索了代码,试图找到可能存在的连接,但是没有任何运气(我会继续寻找,所以这可能仍然是原因,但我也想探索其他途径)。

问题:我可能会遇到 BinaryFormatter 的哪些陷阱/容易犯的错误?我能做些什么来克服这个大小限制?

编辑:添加序列化代码。 “this”是我的包含 11,000 个节点的网络对象。

    Stream testFileStream = File.Create(filename);
    BinaryFormatter serilizer = new BinaryFormatter();
    serilizer.Serialize(testFileStream, this);
    testFileStream.Close();

【问题讨论】:

  • 强调“潜力”。
  • 根据this article实际限制在6M左右
  • 您可能只想自己开始重写和实现序列化。存储在 BinarySerialized 对象中的元数据非常大。私有类小部件 { 私有 int _f = 3;需要 140 个字节来存储...如果我让命名空间更长,更多字节。将 _f 更改为 _field... 4 个字节。即使您重新排序字段并在 DLL 的后一版本中添加一些字段,这也使您能够反序列化,但也许您不需要这些功能并且只想存储具有 4 个字节的小部件的整数值。
  • @user922020 您是否建议覆盖以减少实际存储的数据量或增加可存储的数据量?目前我存储的大部分数据都在 字典和节点列表中,但在不久的将来,该字典将更改为许多明确设置的属性。我不相信在字符串键或属性名称方面真的可以删减任何东西,优先级也应该放在快速反序列化上。
  • 减少。但这真的取决于系统认为什么是“元素”。我会尝试回答,但我没有要测试的数据集。

标签: c# .net serialization


【解决方案1】:

人们正在忽略您的问题,因为它不够具体,无法回答。
但对 BinaryFormatter 有所了解可能会有所帮助。

所以你可能想要做的就是完全避免序列化,只做你自己的读和写。喜欢这个问题...

BinaryFormatter alternatives

如果你完全避免 BinarySerializer,就不会有任何元素计数导致异常。但是 BinarySerializer 确实可以保护自己免受无限循环和其他事情的影响,如果您要序列化某种网络节点图,则必须考虑到这些事情。工作量很大。

在我们进一步了解之前,BinaryFormatter 会序列化私有变量以及公共变量。有没有可能您在私有变量中存储了大量的内容并且没有将其计为每个对象 30 字节的一部分?

为什么要避免序列化?更深入地研究 BinaryFormatter,我们发现它有很多开销,允许它从 DLL 的多个版本流式传输数据,它存储私有变量名称以防您重新排序类中的字段。它有特点。如果您不需要功能并且想要快速的性能,请避免使用它。

示例。

    [Serializable]
    class Widgt2
    {
        private string _fieldWithMuchLongerName = "XXX";
    }

如果你只是将它序列化为内存流,然后查看你得到的字节......

   "\0\0\0\0ÿÿÿÿ\0\0\0\0\0\0\0\f\0\0\0@SOAnswers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\0\0\0SOAnswers.Serialzation1+Widget2\0\0\0_fieldWithMuchLongerName\0\0\0\0\0\0XXX\v"

存储字符串“XXX”需要大量字节。如果您存储像 List 这样的重复,二进制格式化程序会变得更有效率。但它仍然具有意味着开销的功能。

【讨论】:

  • 如果我可以再次 +1 让我知道他们为什么不喜欢我的问题,我会的。
  • 大多数时候他们想要重现错误,这意味着给他们更多的源代码......至少是被序列化的类和某种生成器来创建一万一千个。对于 StackOverflow 问题,我花费的时间比我愿意承认的要多。
  • 我的第一个想法是你的节点图一定是在欺骗 BinarySerializer 进入一个无限循环,但它被编码来检测循环。不知道如何欺骗它。
猜你喜欢
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2012-08-12
相关资源
最近更新 更多