XmlSerializer - 第一次反序列化非常缓慢

7
我有一个解决方案,包含两个项目:一个asp.net MVC应用程序和一个类库。我们称之为MVC项目和CLS项目。
在CLS项目中,我使用了两个不同版本(V1和V2)的XSD文件,并使用xsd2code创建了两个具有相同名称但位于不同命名空间(V1和V2)下的可序列化类。
在MVC项目中,当用户上传一个XML文件时,使用CLS.dll将XML反序列化为对象。当XML文件属于V1类型时,反序列化非常快,但是V2版本的XSD文件更加复杂,反序列化可能需要几分钟时间,仅第一次运行应用程序时会出现这种情况。
我使用Sgen.exe工具为CLS.V2类型创建了一个序列化程序集(CLS.XmlSerializers.dll),以消除动态创建程序集的首次创建,从而提高性能。

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

然而,第一次反序列化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文件始终非常小,但反序列化却很复杂。


“it is slow” 不是完全的保证。但是,很有可能 DLL 只是放错了目录。不要猜测,运行 Fuslogvw.exe 并记录所有绑定。 - Hans Passant
@HansPassant,请查看我更新后的帖子。 - ataravati
你的根对象是否是某种通用集合或容器?正如此处所提到的,它们并不总是与sgen程序集兼容。 - dbc
@dbc,不是的。 - ataravati
请查看我问题的第二次更新。最后我做了一些不同的事情。 - ataravati
显示剩余11条评论
2个回答

4
为了提高XML序列化的性能,每次实例化特定类型的XmlSerializer时,都会动态生成程序集。这只会在应用程序生命周期中发生一次,但这使得它的第一次使用变慢。
当您实例化XmlSerializer时,必须传递要尝试使用该序列化程序实例进行序列化和反序列化的对象的类型。序列化程序检查类型的所有公共字段和属性,以了解实例在运行时引用的哪些类型。然后,它继续使用System.CodeDOM命名空间中的类创建一组处理序列化和反序列化的类的C#代码。在此过程中,XmlSerializer检查反射类型以获取XML序列化属性,以自定义创建的类以符合XML格式定义。这些类然后编译成临时程序集,并由Serialize()和Deserialize()方法调用以执行XML到对象转换。
完整内容:使用XmlSerializer排除常见问题 更多信息:XmlSerializer构造函数性能问题

请仔细阅读我的问题。我已经使用了 sgen 来预编译那些第一次创建的程序集。问题是即使使用了 sgen,也没有任何改变。 - ataravati

1

已知x64 jit编译器存在一些情况下非常缓慢的问题。因此,当代码已经编译时,第二次运行反序列化时会有更好的性能。

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


我之前看过那篇帖子;但是 Sgen.exe 不是应该预编译序列化程序集,以便不必即时编译吗? - ataravati
sgen提前创建临时程序集,但仍需在运行时使用JIT编译器进行编译。为避免这种情况,您需要使用ngen进行编译。您尝试过升级.NET吗?或者这不是一个选项? - Alexander Mokin
我今天会试一下,然后告诉你。 - ataravati
好的,我确实使用了.net 4.6.1,但是它并没有改变任何东西。此外,当我尝试使用ngen.exe安装程序集时,它会给我一个错误,显示“远程过程调用失败”。 - ataravati
奇怪的是,当我从4.5更新到4.6.1时,第一次运行速度提高了20倍以上。这个错误还有更多吗?你尝试在project.dll或cls.xmlserializers.dll上运行ngen了吗?另外,你考虑使用不同的序列化程序了吗? - Alexander Mokin
请查看我问题中的第二次更新。最终我做了一些不同的事情。 - ataravati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接