【问题标题】:Fast and compact object serialization in .NET.NET 中快速紧凑的对象序列化
【发布时间】:2010-10-07 15:22:41
【问题描述】:

我想使用对象序列化通过网络在Mono 服务器和 Silverlight 客户端之间进行通信。 序列化的空间效率和速度非常重要,因为服务器将托管多个实时游戏。

我应该使用什么技术? BinaryFormatter 为该应用程序中不需要的序列化类(版本、文化、类名、属性名等)增加了很多开销。

我可以做些什么来提高空间效率?

【问题讨论】:

  • 天啊!迟到了一个小时;-p

标签: c# .net serialization


【解决方案1】:

您可以使用Protocol Buffers。我正在将我所有的序列化代码从 BinaryFormatter 压缩到 Protocol Buffers 并获得非常好的结果。它在时间和空间上都更有效。

Jon Skeet 和 Marc Gravell 有两个 .NET 实现。

更新:可以在here 找到官方.NET 实现。

【讨论】:

  • 谢谢。这些实现似乎也适用于 silverlight!
  • @Jorge - 顺便说一句,如果您想减少更改,您是否意识到 protobuf-net 可以直接连接到 BinaryFormatter?您可以在根对象上实现 ISerializable,然后调用 Serializer.Serialize/Serializer.Merge
  • @Jorge - 出于好奇,您选择了哪个框架?如果答案是“乔恩的”,我不会生气——我只是感兴趣……我很高兴它对你有用,不管是什么。
  • @Marc - 我正在使用你的。它似乎更灵活,更好地与 .NET 框架集成。
  • Protocol Buffers 链接没有语言标识符(使用较新的 URL 格式)。
【解决方案2】:

我有一些基于 Northwind 数据集的benchmarks for the leading .NET serializers 可用。

@marcgravell 二进制 protobuf-net 是基准测试中最快的实现,比 BCL 中可用的 Microsoft 最快的序列化程序(XML DataContractSerializer)快大约 7 倍。

我还维护了一些开源的高性能 .NET 文本序列化器:

【讨论】:

  • 只是想知道Json serializer 的文件大小比BinaryFormatter 小得多,他们是如何测试的?我编写了自己的序列化程序,它与BinaryFormatter 非常相似,结果却大不相同。对于我的格式化程序,文件大小的范围是 1:1 到 1:7.87。 “永远不要相信不是你自己伪造的统计数据”
  • @FelixK。链接的基准已经包含一个通知和对用于生成测试的基准源代码的引用,即参见:code.google.com/p/servicestack/source/browse/trunk/Common/…
  • 查看基准代码后,我认为文件大小的结果并不代表所有情况,BinaryFormatter 文件大小在使用复杂对象时要小得多。将一堆小对象序列化到格式化程序没有意义(他在为每个对象调用 Serialize 时提交了很多信息),当使用数组而不是文件的大小时,文件的大小要小得多。
  • 基准表明它在锡上做了什么,即Northwind X 次的每个表中都有一个 db 行。如果您想要更具代表性的东西,请提交您自己的基准测试 + 源代码。
  • “领先的 .NET 序列化程序的基准”链接似乎已失效。您有更新的网址吗?
【解决方案3】:

作为作者,我邀请您尝试protobuf-net;它附带了Mono 2.0 和Silverlight 2.0 的二进制文件,并且是fast and efficient。如果您有任何问题,请给我发电子邮件(请参阅我的 StackOverflow 配置文件);支持是免费的。

Jon 的版本(请参阅之前接受的答案)也非常好,但 IMO protobuf-net 版本更适合 C# - 如果您将 C# 与 Java 交谈,Jon 的版本将是理想的,因此您可以在两端。

【讨论】:

  • 我已经在尝试使用 protobuf-net,非常棒的工作,非常感谢!
  • 是否将 ProtoContract 属性添加到类中,并将 ProtoMember 属性添加到使用您的库所需的成员中?
  • @Binoj - 使用“v1”(当前预编译的可下载 dll)“是”。但是,“v2”解决了这个问题(请参阅 marcgravell.blogspot.com/2010/02/protobuf-net-v2-on-iphone.html 了解完整的“v2”详细信息)。它的功能还不完整(要使用它,您必须从主干编译),但现有的“v2”代码适用于一系列简单消息。
  • @Binoj - 作为单独的说明;它必须为ProtoContract - 它也适用于[XmlType]+[XmlElement(Order=n)] 或[DataContract]+[DataMember(Order=n)]。
  • @MarcGravell 你如何处理弱引用对象?我也创建了一些序列化程序,最近我注意到我还没有处理 WeakReference,因为它与反序列化的特殊构造函数一起使用。
【解决方案4】:

虽然我只是使用 .NET,但我也遇到了类似的问题。我想尽可能快速轻松地通过 Internet 发送数据。我没有找到足够优化的东西,所以我自己制作了序列化器,命名为NetSerializer。

NetSerializer 有其局限性,但它们并没有影响我的用例。而且我已经有一段时间没有做基准测试了,但它比我发现的任何其他东西都要快得多。

我没有在 Mono 或 Silverlight 上尝试过。我敢打赌它适用于 Mono,但我不确定 Silverlight 上 DynamicMethods 的支持程度。

【讨论】:

  • 哇,这真是太棒了。谢谢你。如果您可以处理更少的东西(版本控制等),这看起来会快得多。在这种情况下,少即是多:)
【解决方案5】:

您可以尝试使用 JSON。它的带宽效率不如协议缓冲区,但使用 Wireshark 等工具监视消息会容易得多,这在调试问题时很有帮助。 .NET 3.5 附带一个 JSON 序列化程序。

【讨论】:

    【解决方案6】:

    您可以通过 DeflateStream 或 GZipStream 传递数据以在传输前对其进行压缩。这些类位于 System.IO.Compression 命名空间中。

    【讨论】:

    • 谢谢!你知道这会对反序列化速度有多大影响吗?
    • 根据我的经验,它们不适用于大量数据流,但对于大多数其他情况,影响会很小,但您需要尝试并衡量时间影响。只需几行代码即可添加到序列化调用中,因此很容易尝试。
    【解决方案7】:

    我有一个非常相似的问题 - 保存到文件。但以下内容也可以通过网络使用,因为它实际上是为远程处理而设计的。

    解决方案是使用 Simon Hewitt 的库 - 请参阅 Optimizing Serialization in .NET - part 2。

    Part 1的文章指出(粗体是我的重点): “...如果您曾经使用 .NET 远程处理大量 数据,你会发现有问题 可扩展性。对于少量数据,效果很好 足够了,但更大的数量会占用大量的 CPU 和内存, 生成大量数据进行传输,以及 可能会因内存不足异常而失败。还有一个很大的 实际执行的时间问题 序列化 - 大量数据可能使其不可行 用于应用程序....”

    我的特定应用程序得到了类似的结果,40 保存速度快 2 倍,加载速度快 20 倍(从 分钟到秒)。序列化数据的大小是 也减少了很多。具体记不太清了,但是 至少是 2-3 次。

    这很容易上手。然而有一个 陷阱:仅使用 .NET 序列化以获得最高级别 级别数据结构(获取序列化/反序列化 开始),然后调用序列化/反序列化 直接作用于最高级别的字段 数据结构。否则不会有任何加速... 例如,如果一个特定的数据结构(比如 Generic.List) 库不支持然后 .NET 将使用序列化,这是一个禁忌。反而 在客户端代码(或类似代码)中序列化列表。举个例子 参见“'这是我们自己的编码。”在同一个功能 如下所列。

    供参考:code from my application - 参见“注意:这是我们唯一使用内置 .NET ...”的地方。

    【讨论】:

      【解决方案8】:

      您可以尝试 BOIS,它专注于打包数据大小并提供迄今为止最好的打包。 (我还没有看到更好的优化。)

      https://github.com/salarcode/Bois

      【讨论】:

      • +1,但是 MPL?真的吗?谁做的?我屏住呼吸等待速度的提升,哇……它被毁了。
      • 您对 MPL 的哪一部分有疑问?它允许您在开源和商业软件中使用组件。同时保留开发者有权访问该软件中组件的修改版本(如果有的话)。
      • 那很好。我想象它可以访问所有内容。
      • 反序列化非常慢。具有 1 个表、50000 行、50 列的数据集,包含以编程方式生成的字符串数据(所有列都是字符串类型)。序列化到文件需要 2 秒,反序列化需要 15(!) 秒。 BinaryFormatter 总共在 12 秒内完成,因此 BOIS 似乎更慢,因此没有实际用途。
      • @SalarKhalilzadeh:是的,我正在使用适用于 Windows 的桌面解决方案。这在不久的将来不太可能改变。 reconsider you data storage strategy
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-09
      • 2013-09-13
      • 1970-01-01
      相关资源
      最近更新 更多