Как ускорить десериализацию XML? - PullRequest
5 голосов
/ 16 ноября 2011

У меня есть следующий кусок кода

public static object XmlDeserialize(string xml, Type objType)
{
    StringReader stream = null;
    XmlTextReader reader = null;
    try
    {
        XmlSerializer serializer = new XmlSerializer(objType);
        stream = new StringReader(xml); // Read xml data
        reader = new XmlTextReader(stream);  // Create reader
        return serializer.Deserialize(reader);
    }
    finally
    {
        if(stream != null) stream.Close();
        if(reader != null) reader.Close();
    }
}

Сам объект был создан с помощью xsd.exe и выглядит примерно так:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class MyObject {

    private DemographicsCriteriaStateStartAge[] startAgesField;

    private DemographicsCriteriaStateEndAge[] endAgesField;

    private DemographicsCriteriaStateFilter[] selectedFiltersField;

    /// <remarks/>
    [System.Xml.Serialization.XmlArrayItemAttribute("StartAge", IsNullable=false)]
    public DemographicsCriteriaStateStartAge[] StartAges {
        get {
            return this.startAgesField;
        }
        set {
            this.startAgesField = value;
        }
    }
    ...

Метод обычно называется так:

var obj = (MyObject) XmlDeserialize(someXmlString, typeof(MyObject));

Следующая строка кода всегда занимает довольно много времени (по сравнению со всем остальным):

XmlSerializer serializer = new XmlSerializer(objType);

Что здесь происходит, например, это сборка десериализации в фоновом режиме? Почему проблема с производительностью?

Что я могу сделать, чтобы улучшить эту проблему производительности?

Ответы [ 2 ]

5 голосов
/ 16 ноября 2011

Да, он динамически генерирует сборку сериализации во время выполнения. Вы можете изменить это поведение в Visual Studio. Перейдите в свойства проекта и раздел сборки. Для параметра «Создать сборки сериализации» установлено значение true. Это сгенерирует файл наподобие YourProject.XmlSerialiser.dll при компиляции и остановит это узкое место во время выполнения.

Однако следует отметить одно исключение: этот параметр применяется только к типам прокси (например, прокси веб-служб и т. П.). Чтобы заставить Visual Studio 2010 генерировать сборки сериализации для обычных типов, нужно либо связываться с файлом проекта (.csproj) и удалять / proxytypes из вызова Sgen , либо генерировать сообщение шаг сборки для вызова sgen.exe вручную в сборке.

4 голосов
/ 16 ноября 2011

Попробуйте кэшировать экземпляр XmlSerializer для каждого типа на уровне класса, чтобы вам не приходилось каждый раз воссоздавать его, если используется один и тот же тип:

class Foo
{
    private static Dictionary<Type, XmlSerializer> xmls = new Dictionary<Type, XmlSerializer>();

    // ...

    public static object XmlDeserialize(string xml, Type objType)
    {
        StringReader stream = null;
        XmlTextReader reader = null;
        try
        {
            XmlSerializer serializer;
            if(xmls.Contains(objType)) {
                serializer = xmls[objType];
            }
            else {
                serializer = new XmlSerializer(objType);
                xmls[objType] = serializer;
            }           

            stream = new StringReader(xml); // Read xml data
            reader = new XmlTextReader(stream);  // Create reader
            return serializer.Deserialize(reader);
        }
        finally
        {
            if(stream != null) stream.Close();
            if(reader != null) reader.Close();
        }
    }
}
...