【发布时间】:2010-11-09 18:53:09
【问题描述】:
在一个有很多字段的类上调用简单的 XmlSerializer.Deserizlize() 时,我遇到了非常巨大的性能损失。
注意:我在家里写的代码没有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 位),代码第一次大约需要 ONE SECOND(临时序列化类生成,以及所有...),然后它接近于 0。
在 64 位系统中运行应用程序,代码第一次耗时 ONE MINUTE,然后接近 0。
在 64 位系统中,对于一个大类,在第一次执行 XmlSerializer 期间,什么可能会使系统挂起这么长时间?
现在我不确定我是否必须责怪临时类生成/删除、xml 名称表初始化、CAS、Windows 搜索、防病毒或圣诞老人......
剧透
这是我的测试,如果您不想被我的(可能的)分析错误所牵制,请不要阅读此内容。
- 从 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
编辑我忘了说我用进程监视器分析了执行,我没有看到我的应用程序或 csc.exe 或任何与框架相关的任务需要很长时间.系统只是做其他事情(或者我遗漏了一些东西),比如防病毒、explorer.exe、Windows 搜索索引(已经尝试关闭它们)
【问题讨论】:
-
sgen 有什么问题?你为什么不想走那条路?
-
我的 Foo() 类,以及调用 XmlDeserializer 的代码,都是由旧系统动态生成的,无法重构太多。我已经有了一个可接受的解决方案(使用 system.diagnostic 开关设置),但我真的很想知道是什么挂起系统 :)
-
所以你的系统不是很忙,它只是坐在那里?那种暗示某种超时,可能试图解析 XML 模式或其他东西。不过,我预计 32 位和 64 位环境中的延迟相同。除非该模式以前以某种方式以 32 位模式缓存。重新设计。 . .
-
class Foo 不能反序列化,因为它是内部的而不是公共的(在您的示例中)。在我的系统上,32 位发布版本需要 0.055 秒来反序列化。与您的结果一样,我的 64 位版本需要 12.5 秒!所以那里的减速大约是 227 倍。
-
+1 希望这个问题得到一些专业的关注。有趣的情况。
标签: .net 64-bit xmlserializer