如何让XML反序列化更快?

发布于 2024-12-16 14:01:45 字数 1820 浏览 0 评论 0原文

我有以下一段代码

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);

这里发生了什么,例如它是否在后台编译反序列化程序集?为什么会出现性能问题?

我可以做什么来改善这个性能问题?

I have the following piece of code

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();
    }
}

The object itself has been generated via xsd.exe and looks kind of like this:

/// <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;
        }
    }
    ...

The method is typically called like this:

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

The following line of code always take a pretty large chunk of time (compared to everything else):

XmlSerializer serializer = new XmlSerializer(objType);

What is going on here, e.g. is it compiling a deserialization assembly in the background? Why the performance issue?

What can I do to ameliorate this performance problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁月苍老的讽刺 2024-12-23 14:01:45

尝试在类级别缓存每种类型的 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();
        }
    }
}

Try caching the instance of the XmlSerializer for each type at the class level so you don't have to recreate it each time if the same type is used:

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();
        }
    }
}
空‖城人不在 2024-12-23 14:01:45

是的,它在运行时动态生成序列化程序集。您可以在 Visual Studio 中更改此行为。转到项目属性和构建部分。有一个“生成序列化程序集”的设置,将其设置为 true。当您编译时,这将生成一个类似 YourProject.XmlSerialiser.dll 的文件,并将在运行时阻止此瓶颈。

然而,需要注意的一个例外是,此设置仅适用于代理类型(例如,Web 服务代理等)。要真正强制 Visual Studio 2010 为常规类型生成序列化程序集,必须要么搞乱项目文件 (.csproj) 并从 Sgen 调用或生成构建后步骤在程序集上手动调用 sgen.exe。

Yes, it is dynamically generating a serialisation assembly at run time. You can change this behaviour in Visual Studio. Go to the project properties and the build section. There is a setting for "Generate serialization assemblies" set it to true. This will generate a file like YourProject.XmlSerialiser.dll when you compile and will stop this bottleneck at run time.

One exception to note, however, is that this setting applies only to proxy types (for example, web service proxies and the like). To actually force Visual Studio 2010 to generate serialization assemblies for regular types, one must either mess with the project file (.csproj) and remove /proxytypes from the Sgen call or generate a post-build step to manually call sgen.exe on the assembly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文