c#-.NET中快速紧凑的对象序列化

我想使用对象序列化在Mono服务器和Silverlight客户端之间通过网络进行通信。非常重要的一点是,序列化不仅要节省空间而且要快速,因为服务器将要托管多个实时游戏。

我应该使用什么技术? BinaryFormatter给序列化类(版本,区域性,类名,属性名等)增加了很多开销,而在此应用程序中则不需要。

我该怎么做才能提高空间利用率?

Dennis Kempin asked 2019-11-06T20:53:40Z
8个解决方案
68 votes

您可以使用协议缓冲区。 我将所有我的序列化代码从BinaryFormatter压缩后更改为Protocol Buffer,并获得了很好的结果。 在时间和空间上效率更高。

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

更新:官方.NET实现可在此处找到。

Jorge Villuendas Zapatero answered 2019-11-06T20:54:04Z
52 votes

我有一些基于Northwind数据集的领先.NET序列化程序的基准。

Northwind .NET serialization benchmarks

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

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

  • JSV TypeSerializer一种紧凑,干净,类似于JSON + CSV的格式,比DataContractSerializer快3.1倍
  • 以及快2.6倍的JsonSerializer。
mythz answered 2019-11-06T20:54:53Z
28 votes

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

Jon的版本(请参阅先前接受的答案)也非常好,但是IMO的protobuf-net版本对于C#来说更惯用了-如果您正在将C#与Java进行通讯,那么Jon的版本将是理想的选择,因此您在两端都可以使用类似的API。

Marc Gravell answered 2019-11-06T20:55:24Z
8 votes

我有一个类似的问题,尽管我只是使用.NET。 我想尽可能快速,轻松地通过Internet发送数据。 我没有找到任何可以优化的东西,所以我制作了自己的序列化程序NetSerializer。

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

我还没有在Mono或Silverlight上尝试过。 我敢打赌它可以在Mono上运行,但是我不确定Silverlight上对DynamicMethods的支持水平。

Tomba answered 2019-11-06T20:56:01Z
5 votes

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

Pablote answered 2019-11-06T20:56:24Z
4 votes

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

Sean answered 2019-11-06T20:56:48Z
3 votes

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

解决方案是使用Simon Hewitt的库-请参阅优化.NET中的序列化-第2部分

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

对于我的特定应用,我得到了类似的结果40保存速度提高了两倍,加载速度提高了20倍(来自分钟到几秒钟)。 序列化数据的大小为也大大减少了。 我记不清了,但是是至少2-3倍。

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

参考:我的应用程序中的代码-请参阅“注意:这是我们使用内置.NET的唯一位置...”附近。

Peter Mortensen answered 2019-11-06T20:57:46Z
2 votes

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

[https://github.com/salarcode/Bois]

Salar answered 2019-11-06T20:58:16Z
translate from https://stackoverflow.com:/questions/549128/fast-and-compact-object-serialization-in-net