簡體   English   中英

使用生成的XmlSerializer類優化性能

[英]Performance optimizing use of generated XmlSerializer class

我們的應用程序正在讀取一些XML文件。 XML格式是固定的,因此我們可以使用XmlSerializer輕松讀取它們。

我使用以下代碼讀取XML文件並將其轉換為類:

public static T FromXml<T>(this string xml) where T : class
{
    if (string.IsNullOrEmpty(xml))
    {
        return default(T);
    }

    XmlSerializer xmlserializer = new XmlSerializer(typeof(T));

    XmlTextReader textReader = new XmlTextReader(new StringReader(xml));
    textReader.Normalization = false;

    XmlReaderSettings settings = new XmlReaderSettings();

    T value;

    using (XmlReader reader = XmlReader.Create(textReader, settings))
    {
        value = (T)xmlserializer.Deserialize(reader);
    }

    return value;
}

但是,存在一些性能問題。 第一次使用此代碼的特定類型的TXmlSerializer生成一個Project.XmlSerializer.dll文件。

很好,但是要花費一些寶貴的毫秒(在我的情況下約為900毫秒)。 可以通過使用XML Serializer Generator(sgen)預先生成該程序集來避免這種情況。 這將時間減少到大約一半。 主要是由於組件的讀取和反射。

我想通過將XmlSerializer類引入實際類所在的程序集中進一步優化此方法 ,但是我找不到讓XmlSerializer知道不讀取外部程序集,而是使用當前程序集中的序列化器的方法。

有什么想法如何做到這一點或另一種方式使這項工作嗎? (我無法預加載它們,因為大多數序列化的類在啟動時使用)


使用ANTS Profiler進行的分析(來自其他計算機的指標,但模式相同):

在此處輸入圖片說明

平原。 在生成和加載XmlSerializer程序集的大部分時間(300ms + 400ms = 700ms)中丟失了。

在此處輸入圖片說明

用sgen生成的程序集。 大部分時間(336ms)浪費在加載XmlSerializer程序集上。

在此處輸入圖片說明

當將程序集的實際源包含在項目中並直接調用序列化程序時,操作將降至456ms(第一時間為1s,第二時間為556ms)。

注意:OP發布了一個示例配置: http : //pastebin.com/d67nch3R

根據樣本配置和您遇到的問題的類型,有兩種蠻力方法,幾乎​​可以保證達到目的,兩種方法最終都完全放棄了XML序列化器。

1號路線

放棄XML序列化,並使用XDocument從XML中獲取數據。

2號線

使用json和Newtonsoft Json來存儲和加載配置。 它的性能應該比XML Serializer好很多

樣本json對應內容如下所示:

{
  "Connections": {
    "-default": "Local\\SqlServer",
    "-forcedefault": "false",
    "group": {
      "-name": "Local",
      "connection": {
        "-name": "SqlServer",
        "database": {
          "-provider": "SqlServer",
          "-connectionString": "blah"
        }
      }
    }
  },
  "LastLanguage": "en",
  "UserName": "un",
  "SavePassword": "true",
  "AutoConnect": "false",
  "Password": "someObfuscatedHashedPassword==",
  "ConnectionName": "Somewhere\\Database",
  "LastAvailableBandwidth": "0",
  "LastAvailableLatency": "0",
  "DateLastConnectionSuccesful": "2014-08-13T15:21:35.9663654+02:00"
}

並加載它:

UserSettings settings = JsonConvert.DeserializeObject<UserSettings>(File.ReadAllText("settings.json"))

除非您在應用程序啟動時就進行序列化,否則一種方法將是強制CLR提前加載甚至編譯您正在使用的任何類,可能會在啟動后立即在后台運行的線程中您的應用。

例如:

foreach (Assembly a in assembliesThatShouldBeCompileed)
    foreach (Type type in a.GetTypes())
        if (!type.IsAbstract && type.IsClass)
        {
            foreach (MethodInfo method in type.GetMethods(
                                BindingFlags.DeclaredOnly |
                                BindingFlags.NonPublic |
                                BindingFlags.Public |
                                BindingFlags.Instance |
                                BindingFlags.Static))
            {
                if (method.ContainsGenericParameters || 
                    method.IsGenericMethod || 
                    method.IsGenericMethodDefinition)
                    continue;

                if ((method.Attributes & MethodAttributes.PinvokeImpl) > 0)
                    continue;

                System.Runtime.CompilerServices
                   .RuntimeHelpers.PrepareMethod(method.MethodHandle);
            }
        }

然而,很奇怪的是,您的性能分析似乎表明,如果SGEN的代碼在單獨的程序集中,則沒有太大的區別,而加載似乎是瓶頸。 我想知道圖表在同一裝配中的情況如何?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM