`Serializable` 对象的更快序列化
Posted
技术标签:
【中文标题】`Serializable` 对象的更快序列化【英文标题】:Faster serialization of `Serializable` objects 【发布时间】:2014-10-06 05:58:44 【问题描述】:我们的客户端/服务器应用使用NetDataContractSerializer
序列化任意Serializable
对象。
BinaryFormatter
的输出会更小一些,however 的性能并不是真正的better。
现在可以使用更小的表示形式(例如,XmlSerializer
和 DataContractSerializer
、Json、Protocol Buffers、Thrift 等的输出),这也恰好可以更快地进行序列化和反序列化。
但是,为了使用这些,我必须访问每个 Serializable
类并添加属性并可能更改字段的访问级别等。这些类不仅分布在许多不同的内部项目中,但是我们的客户有自己的带有Serializable
类的dll,必须对其进行修改。换言之,一项重大事业。
Serializable
对象是否有任何其他性能改进和潜在的尺寸减小(gzipping 等除外)?
【问题讨论】:
【参考方案1】:我在查看 Lars Kemmann 的建议后得出的结论:除了NetDataContractSerializer
/BinaryFormatter
之外,没有其他选择可以以相同的方式序列化和反序列化。
我和Json.NET
玩过,它有点工作,但通常情况下,魔鬼在细节中(另请参阅我的 cmets 对 Lars 的回答):
用现实生活中的对象进行测试,结果发现我的反序列化对象并非 100% 等同于原始对象,源于未序列化的超类中的字段。至少粗略检查后是这样的。
Protobuf-net
也不是一个选项,因为你
-
必须在序列化之前手动注册每个(非 protobuf 注释的)类型
在反序列化时必须指定确切的类型
它抱怨没有无参数构造函数的类
【讨论】:
【参考方案2】:其中许多序列化程序不需要自定义属性 - 事实上,有些是专门设计用于识别和使用 SerializableAttribute
。参见,例如:
SerializableAttribute
protobuf-net's approach 允许运行时配置并且还支持DataContractAttribute
(它更准确地定义了您在有线协议中想要的特性)。你当然可以在运行时配置 protobuf-net 来做你想做的事。
Json.NET 示例:
var settings = new JsonSerializerSettings
TypeNameHandling = TypeNameHandling.All,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
;
string serialized = JsonConvert.SerializeObject(obj, settings);
var deserialized = JsonConvert.DeserializeObject(serialized, settings);
更新:您不需要 fork Json.NET 来进行类型实例化。我正在使用this article 中所述的自定义JsonConverter
。
【讨论】:
引用您的 protobuf 链接:Contract types Protobuf-net expects contract types to be explicitly marked as such; types can be marked [ProtoContract], [DataContract] or [XmlType] for this purpose ([Serializable] is not required and is not used)
我就是这么说的。还引用了该 protobuf 项目 wiki 页面的第一行:“请注意,在 v2 中,所有内容也可以在运行时配置,而无需编辑任何类型。”
我可以让 Json.NET 工作(并在您的答案中添加了一个示例),但在 protobuf-net 的情况下,我 a) 似乎必须添加每个(非 protobuf-annotated)类型在序列化之前手动 b)在反序列化时指定确切的类型(例如,不是常见的超级接口/类) c)protobuf 抱怨,除非有无参数的构造函数。 IE。它似乎不能替代 BinaryFormatter/NetDataContractSerializer。
感谢您添加。是的,绝对有可能的限制。如果您正在寻找性能更好且行为没有任何重大变化的直接替代品,我认为您不会找到 - 微软的性能工程师获得高薪是有原因的。 :) 我会说绝对值得考虑添加[DataContract]
注释的好处,因为正如我所说[Serializable]
真的不适合有线传输,除非您确定要紧密耦合您的客户端和服务器。 [DataContract]
将打开更多选项。
好吧,我不确定 NetDataContractSerializer
和 Json.NET
是否 100% 等效,但在我使用实际复杂的嵌套对象进行的测试中,前者花费的时间是后者的 1.5 倍,这让我有点惊讶,因为 MS 可以在内部做很多 Json.NET 做不到的“不安全”的事情。以上是关于`Serializable` 对象的更快序列化的主要内容,如果未能解决你的问题,请参考以下文章