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

2024-01-23

我正在经历一个真正的HUGE在具有大量字段的类上调用简单的 XmlSerializer.Deserialize() 时会造成性能损失。

NOTE:我在家里没有使用 Visual Studio 编写代码,因此可能会有一些错误。

我的可序列化类是扁平的,有数百个字段:

[Serializable]
class Foo
{
    public Foo() { }

    [XmlElement(ElementName = "Field1")]
    public string Field1;

    // [...] 500 Fields defined in the same way

    [XmlElement(ElementName = "Field500")]
    public string Field500;
}

我的应用程序反序列化输入字符串(即使很小):

 StringReader sr = new StringReader(@"<Foo><Field1>foo</Field1></Foo>");
 XmlSerializer serializer = new XmlSerializer(typeof(Foo));
 object o = serializer.Deserialize(sr);

在 32 位系统中运行应用程序(或使用 corflags.exe 强制使用 32 位),代码大约需要一秒第一次(临时序列化类生成,以及所有...),然后它接近 0。

在 64 位系统中运行应用程序,代码需要等一下第一次,那么它就接近于0。

什么可能会导致系统挂起这么长时间,在 64 位系统中第一次执行 XmlSerializer 时,对于一个大类?

现在我不确定我是否必须责怪临时类生成/删除、xml 名称表初始化、CAS、Windows 搜索、防病毒或圣诞老人......

SPOILERS

这是我的测试,如果您不想被我的(可能的)analysys 错误所困扰,请不要阅读本文。

  • 从 Visual Studio 调试器运行代码使代码即使在 64 位系统中也能快速运行
  • 添加(完全未记录的)system.diagnostic 开关“XmlSerialization.Compile”,可防止系统删除序列化临时类,使代码即使在 64 位系统中也能快速运行
  • 采用运行时创建的临时 FooXmlSerializer 类(包括我的项目中的 .cs),并使用它代替 XmlSerializer,使代码即使在 64 位系统中也能快速运行
  • 使用 sgen.exe 创建相同的 FooXmlSerializer 类(包括我的项目中的 .cs),并使用它代替 XmlSerializer,使代码即使在 64 位系统中也能快速运行
  • 使用 sgen.exe 创建相同的 FooXmlSerializer 类,在我的项目中引用 Foo.XmlSerializers.dll 程序集,并使用它而不是 XmlSerializer,使得代码即使在 64 位系统中也运行缓慢(这让我很烦恼)
  • 仅当反序列化的输入实际上包含大类的字段时,才会发生性能损失(这也让我很烦恼)

为了进一步解释最后一点,如果我有一堂课:

[Serializable]
class Bar
{
    public Bar() { }

    [XmlElement(ElementName = "Foo")]
    public Foo Foo; // my class with 500 fields
}

仅当传递 Foo 子级时,反序列化才会很慢。即使我已经执行了反序列化:

 StringReader sr = new StringReader(@"<Bar></Bar>");
 XmlSerializer serializer = new XmlSerializer(typeof(Bar));
 object o = serializer.Deserialize(sr); // FAST

 StringReader sr = new StringReader(@"<Bar><Foo><Field1>foo</Field1></Foo></Bar>");
 XmlSerializer serializer = new XmlSerializer(typeof(Bar));
 object o = serializer.Deserialize(sr); // SLOW

EDIT我忘了说我使用 Process Monitor 分析了执行情况,并且我没有看到我的应用程序或 csc.exe 或任何与框架相关的任务需要很长时间。系统只是做其他事情(或者我遗漏了一些东西),比如防病毒、explorer.exe、Windows 搜索索引(已经尝试将它们关闭)


我不知道这是否相关,但我遇到了 XSLT 问题并发现那些相当有趣的评论 http://connect.microsoft.com/VisualStudio/feedback/details/508748/memory-consumption-alot-higher-on-x64-for-xslcompiledtransform-transform-then-on-x86Microsoft 关于 64 位 JITter 的信息:

问题的根源与两件事有关:首先,x64 JIT 编译器有一些二次缩放的算法。不幸的是,其中之一是调试信息生成器。因此对于非常大的方法,它确实会失控。

[...]

64 位 JIT 中的一些算法具有多项式缩放。我们实际上正在致力于将 32 位 JIT 编译器移植到 x64,但这要等到next运行时的并行版本(如“2.0 和 4.0 并行运行,但 3.0/3.5/3.5SP1 是“就地”版本)。我已将其切换为“建议”因此我可以将其附加到 JIT 吞吐量工作项,以确保在新移植的 JIT 准备好交付时修复此问题。

同样,这是一个完全不同的问题,但在我看来,64 位 JITter 注释是通用的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XmlSerializer 在 64 位系统上启动时性能损失巨大 的相关文章

随机推荐