Я испытываю действительно сильную потерю производительности HUGE при вызове простого 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-битных системах (или с 32-битным принудительным с помощью corflags.exe), код занимает примерно ONE SECOND в первый раз (генерация класса сериализации temp и все...), затем он близок к 0.
Запуск приложения в 64-битных системах, код принимает ONE MINUTE в первый раз, затем он близок к 0.
Что может зависеть система в течение такого длительного времени, во время первого выполнения XmlSerializer, для большого класса в 64-битной системе?
В настоящий момент я не уверен, что я должен обвинять создание/удаление классов temp, инициализацию таблицы имен xml, CAS, Windows Search, AntiVirus или Santa Claus...
СПОЙЛЕРЫ
Вот мои тесты, не читайте это, если вы не хотите, чтобы меня отвлекали мои (возможные) ошибки анализа.
- Запуск кода из отладчика Visual Studio заставляет код запускать FAST даже в 64-битных системах.
- Добавление (полностью недокументированного) system.diagnostic-переключателя "XmlSerialization.Compile", который не позволяет системе удалять временные классы сериализации, заставляет код запускать FAST даже в 64-разрядных системах.
- Взятие временного класса FooXmlSerializer, созданного средой выполнения, включая .cs в моем проекте и использование его вместо XmlSerializer, заставляет код запускать FAST даже в 64-битных системах.
- Создание того же класса FooXmlSerializer с sgen.exe, включая .cs в моем проекте и использование его вместо XmlSerializer, заставляет код запускать FAST даже в 64-битных системах.
- Создание того же класса FooXmlSerializer с sgen.exe, ссылающегося на сборку Foo.XmlSerializers.dll в моем проекте и использование его вместо XmlSerializer, заставляет код запускать SLOW даже в 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
ИЗМЕНИТЬ Я забыл сказать, что проанализировал выполнение с помощью Process Monitor, и я не вижу, чтобы какая-либо задача занимала много времени из моего приложения или из csc.exe или что-то связанное с Framework, Система просто делает другие вещи (или я что-то упускаю), например, антивирус, explorer.exe, индексирование Windows Search (уже пытался отключить их)