为什么DataContract比Serializable更快?

时间:2012-09-07 11:12:01

标签: c# .net datacontractserializer xml-deserialization

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

[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秒)。

为什么?

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

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

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

3 个答案:

答案 0 :(得分:1)

我不是百分百肯定,但我的猜测是:

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

2)使用[Serializable],序列化程序检查对象的所有字段,并且必须使用反射来执行此操作,这很昂贵。

答案 1 :(得分:1)

在第一次通话后评论有关序列化加速的更新:

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

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

答案 2 :(得分:1)

您可能正在调试模式下进行测试,而是需要在发布模式下进行测试,以确保您的序列化设备能够正常运行。

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

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

可以找到更多信息:

XmlSerializer startup HUGE performance loss on 64bit systems

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