XmlSerializer - 第一个反序列化非常慢

时间:2017-08-24 21:27:57

标签: c# serialization xml-serialization xmlserializer sgen

我有两个项目的解决方案;一个asp.net MVC应用程序和一个类库。我们称之为项目MVC和项目CLS。

在项目CLS中,有一个XSD文件的两个不同版本(V1和V2),我用它来创建两个具有相同名称的可序列化类,但在不同的命名空间(V1和V2)下使用{{3} }。

在MVC项目中,当用户上传XML文件时,CLS.dll用于将XML反序列化为对象。当XML文件的类型为V1时,反序列化速度非常快,但V2版本的XSD文件要复杂得多,反序列化可能需要几分钟,而且只是第一次(事后很快) ,直到再次运行应用程序。)

我使用xsd2code工具为CLS.V2类型创建了一个序列化程序集(CLS.XmlSerializers.dll),以便在运行时消除首次创建程序集,从而改进性能

我已成功设法将Sgen任务添加到Post Build事件中,每次构建项目时都会创建程序集CLS.XmlSerializers.dll。另外,我在Sgen.exe中使用了单元测试代码来确保程序集已加载,并且确实已加载。测试通过成功。

但是,第一次对XML文件进行反序列化时,需要很长时间。所以,还有一些事情应该是错的。但是,我不知道是什么。请帮忙。

更新

我按照评论中的建议使用了Fuslogvw.exe,我可以看到CLS.XmlSerializers.dll已成功加载。那么,为什么第一次对XML文件进行反序列化需要大约一分钟,但每次只需不到一秒钟?

更新2:

两个XSD文件之间的区别之一是第二个(V2)引用了一个非常大的XSD文件,该文件包含主文件中使用的某些xs:enumeration类型的定义。而且,这就是反序列化需要很长时间的原因。因为我需要做的就是将XML文件反序列化为对象,而不需要根据这些枚举验证属性和元素的值,我最终删除了对该XSD文件的引用,并用它们替换所有枚举类型基类型(在本例中为xs:string)。现在,V2的反序列化速度与V1一样快,我甚至不需要使用Sgen.exe。我猜Sgen.exe仅在需要反序列化非常大的XML文件的情况下才有用。就我而言,XML文件总是很小,但是反序列化很复杂。

2 个答案:

答案 0 :(得分:3)

为了提高XML序列化的性能,每次为特定类型首次实例化XmlSerializer时,都会动态生成程序集。它只在应用程序生命周期中发生一次,但这使得它的第一次使用变慢。

  

实例化XmlSerializer时,必须传递将尝试使用该序列化程序实例序列化和反序列化的对象的类型。序列化程序检查Type的所有公共字段和属性,以了解实例在运行时引用的类型。然后,它继续为一组类创建C#代码,以使用System.CodeDOM命名空间中的类来处理序列化和反序列化。在此过程中,XmlSerializer检查XML序列化属性的反射类型,以将创建的类自定义为XML格式定义。 然后将这些类编译为临时程序集,并由Serialize()和Deserialize()方法调用,以执行XML到对象的转换。

完整内容:Troubleshooting Common Problems with the XmlSerializer

更多信息:XmlSerializer Constructor Performance Issues

答案 1 :(得分:1)

这是x64 jit编译器的一个已知问题,在某些情况下可能会非常慢。这就是为什么当代码已经编译时第二次运行deserializtion时你有更好的性能。

尝试使用.net 4.6或更高版本,它具有新版本的x64 jit编译器(RyuJIT)。如果无法更新.net版本,请查看此thread