多くのフィールドを持つクラスで単純な 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 ビットを強制) でアプリケーションを実行すると、コードは最初に約 1 秒かかります(一時シリアル化クラスの生成、およびすべて...)、その後は 0 に近くなります。
64 ビット システムでアプリケーションを実行すると、コードは最初は 1 分かかり、その後は 0 に近くなります。
XmlSerializer の最初の実行中に、大きなクラスの 64 ビット システムで、システムがこれほど長時間ハングする可能性があるのは何でしょうか?
現時点では、一時クラスの生成/削除、xml 名テーブルの初期化、CAS、Windows サーチ、アンチウイルス、またはサンタ クロースのせいにする必要があるかどうかはわかりません...
スポイラー
ここに私のテストがあります。私の (可能性のある) 分析ミスによって脱線したくない場合は、これを読まないでください。
- Visual Studio デバッガーからコードを実行すると、64 ビット システムでもコードが高速に実行されます。
- (まったく文書化されていない) system.diagnostic スイッチ "XmlSerialization.Compile" を追加すると、システムがシリアライゼーション一時クラスを削除するのを防ぐことができ、64 ビット システムでもコードが高速に実行されます。
- ランタイムによって作成された一時的な FooXmlSerializer クラス (プロジェクトの .cs を含む) を取得し、XmlSerializer の代わりに使用すると、64 ビット システムでもコードが高速に実行されます。
- 私のプロジェクトに.csを含め、sgen.exeで同じFooXmlSerializerクラスを作成し、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 Search のインデックス作成 (既にそれらをオフにしようとしています) など、他の処理を実行するだけです (または、何か不足しています)。