Я испытываю действительно ОГРОМНУЮ потерю производительности при вызове простого 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) код занимает около ОДНОЙ СЕКУНДЫ в первый раз (генерация временного класса сериализации и все такое...), затем он близок к 0.
При запуске приложения в 64-битных системах код занимает ОДНУ МИНУТУ в первый раз, а затем близок к 0.
Что могло привести к зависанию системы на такое долгое время во время первого выполнения XmlSerializer для большого класса в 64-битной системе?
Прямо сейчас я не уверен, должен ли я винить создание/удаление временного класса, инициализацию таблицы имен xml, CAS, поиск Windows, антивирус или Санта-Клауса...
СПОЙЛЕРЫ
Вот мои тесты, не читайте это, если не хотите отвлекаться на мои (возможные) ошибки анализа.
- Запуск кода из отладчика Visual Studio заставляет код работать БЫСТРО даже в 64-битных системах.
- Добавление (полностью недокументированного) переключателя system.diagnostic «XmlSerialization.Compile», который не позволяет системе удалять временные классы сериализации, заставляет код работать БЫСТРО даже в 64-битных системах.
- Взяв временный класс FooXmlSerializer, созданный средой выполнения, включая .cs в моем проекте, и используя его вместо XmlSerializer, код выполняется БЫСТРО даже в 64-разрядных системах.
- Создание того же класса FooXmlSerializer с sgen.exe, включая .cs в моем проекте, и использование его вместо XmlSerializer позволяет выполнять код БЫСТРО даже в 64-разрядных системах.
- Создание того же класса FooXmlSerializer с sgen.exe, ссылка на сборку 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, или в чем-либо, связанном с Framework. Система просто делает другие вещи (или я что-то упускаю), такие как антивирус, explorer.exe, индексация поиска Windows (уже пытался их отключить)