3

我尝试使用下面的代码对自定义对象进行序列化和反序列化。

[Serializable]
public class TaskProperty
{
    public int Id { get; set; }
    public DateTime ScheduleTime { get; set; }
    public TimeSpan InitializationTime { get; set; }
    public Nullable<DateTime> InstantOfStart { get; set; }
    public TimeSpan TotalElapsedTime { get; set; }
}

// Main
var serializer = new DataContractSerializer(typeof(TaskProperty));
var reader = new FileStream("myfile.xml", FileMode.Open);
TaskProperty deserialized = (TaskProperty)(serializer.ReadObject(reader));
reader.Close();
Console.WriteLine("deserialized: {0}", deserialized);

如果TaskProperty类用DataContract属性修饰(并且DataMember每个属性都用属性),反序列化比用属性修饰时快得多Serializable

  • 使用DataContractDataMember属性,反序列化几乎是立即的;
  • 使用Serializable属性,反序列化非常慢(大约需要 30 秒)。

为什么?

更新...此外,如果反序列化之前是序列化相同类型的对象(显然具有不同的内容),则序列化速度慢而反序列化速度快。类似地,如果序列化之前是反序列化相同类型的对象,反序列化速度很慢,而序列化速度很快。

更新 2...为了完整起见,我添加了应该序列化和反序列化的自定义类。

更新3 ...好吧,也许我发现了影响Serializable属性的缓慢的原因,但我不明白为什么。本质上,如果我明确声明与五个属性相关的五个私有字段,那么第一次序列化(或反序列化)几乎是即时的。为什么?

4

3 回答 3

1

只是为了评论您在第一次通话后加速序列化的更新:

序列化器可能正在使用反射来构建元数据,并可能使用动态方法来执行该类型的序列化,这是它第一次必须处理该类型。

我知道如果我正在编写通用序列化程序,那就是我会做的;反映所有属性,ILEmit 一个动态方法来执行实际的序列化,并保存生成的方法,以便在再次序列化或反序列化相同类型时使用。

于 2012-09-07T15:33:48.307 回答
1

您可能正在调试模式下进行测试,而需要在具有正确 NGEN 的序列化程序的发布模式下进行测试。

编辑:关于您上面的评论“平均性能提高,因为只有第一次序列化速度较慢。” 几乎证实了我对缺乏 NGEN 是罪魁祸首的怀疑。您需要在项目属性 < 构建 < 生成序列化程序集下查看您的项目构建设置

您想验证发布版本没有禁用它(如果需要,您也可以启用它进行调试)

可以找到一些进一步的信息:

XmlSerializer 在 64 位系统上启动巨大的性能损失

http://blogs.msdn.com/b/billwert/archive/2008/02/23/use-of-sgen-exe-to-avoid-common-xmlserializer-performance-pitfalls.aspx

于 2012-09-07T15:38:46.873 回答
1

我不是 100% 确定,但我的猜测是:

1) .NET 将属性信息嵌入到程序集的元数据中,因此数据协定序列化程序不必进行反射来查找类的所有数据成员属性。

2) 使用[Serializable],序列化器检查对象的所有字段,并且必须使用反射来做到这一点,这是昂贵的。

于 2012-09-07T11:17:47.477 回答