2008-11-10 44 views
7

我將小的(2-10 KB)XML文檔作爲輸入傳遞給WCF服務。現在我兩個可選的從輸入的XML中讀取數據值XPath vs DeSerialization:讀取操作的性能更好

  1. 反序列化到一個強類型的對象和使用對象屬性來訪問值
  2. 使用XPath訪問值

哪種方式速度更快?一些統計數據支持你的答案會很好。

回答

7

我會反序列化它。

如果您使用xpath,您將反序列化(或「加載」)到XmlDocument或其他東西。所以這兩種解決方案都使用時間反序列化。完成此操作後,由於解析該字符串,解析名稱,執行函數等所花費的時間,xpath將變慢。另外,如果你使用xpath,你不會得到類型安全。您的編譯器無法爲您檢查xpath語法。

如果您使用XmlSerializer和類,您將獲得靜態類型。真正快速訪問你的數據,如果你想用xpath查詢它們,仍然有辦法做到這一點。

此外,我想說,你的代碼可能會更容易理解與類。

唯一的缺點是xml必須始終符合相同的模式,但在您的情況下這可能不是真正的問題。

我希望你原諒沒有統計數據,我認爲這些論點足夠強大,沒有例子。如果您想要最終答案,請嘗試兩種方法並準備好秒錶。

4

還有第三種方法是堅持使用XML,但可以使用任何您正在使用的XML API進行查詢 - 例如LINQ to XML使得查詢在代碼中相對簡單。

您是否已經將文本解析爲XML文檔?

您是否確信這實際上是您的代碼中的一個重大性能瓶頸? (例如,如果您正在與數據庫進行交談,那麼不必擔心此問題 - 首先讓它以最簡單的方式工作)

查詢是否總是相同,或者它們是動態的某種方式?

你有一個真實的消息和查詢測試設備嗎?如果不是,您需要一個以評估您的數據給出的任何答案。如果你這樣做,我希望它可以很容易地嘗試它:)

+0

感謝喬恩, >您是否已分析的文本轉換爲XML文檔? 是的,我收到一個XMLDocument作爲輸入 >查詢是否總是相同,還是以某種方式動態? 查詢總是一樣的。 我沒有實際的數據來測試,現在一個大概的想法就足夠了 – 2008-11-10 12:51:37

+0

我建議你現在以最簡單的方式編寫它(可能是XPath),並測量查詢所花費的時間與整個請求的性能。如果這個比例變得顯着,重新審視這個問題。 – 2008-11-10 12:55:56

1

這裏有4個的情況下,任何時候都蜱和配售:

  • 的XmlSerializer(最慢4日)
  • 實現IXmlSerializable的(3)
  • 手卷(自定義)(1)
  • 的XElement (2nd)

樣本對象被讀取1000次。

你應該在意嗎?對於大多數情況,請使用內置到.net中的默認序列化程序。沒有必要偏離,這將產生最少量的代碼。這些應該是綽綽有餘,提供類型安全,並釋放自己與你的時間做更有意義的事情。在某些情況下,如果您希望從大型XML結構中挑選某些數據元素,XElement可能會很有用,但即使如此,也應該將這些元素放入強類型的DTO中。但請記住,所有方法都非常快。我已經親自在幾毫秒內序列化了一個非常廣泛和深入的對象模型(超過400個分組)。對於較小和不重要的對象,這將是子響應時間。 XMLSerializer的預熱速度比其他的慢,但可以通過SGEN進行緩解或在啓動時進行一些初始化。

詳細信息和代碼...

Xml序列

[Serializable] 
    public class FoobarXml 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
     public bool IsContent { get; set; } 

     [XmlElement(DataType = "date")] 
     public DateTime BirthDay { get; set; } 
    } 

第一次:2448965

1000閱讀平均分:245

IXmlSerializable的

public class FoobarIXml : IXmlSerializable 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
     public bool IsContent { get; set; } 
     public DateTime BirthDay { get; set; } 

     public XmlSchema GetSchema() 
     { 
      return null; 
     } 

     public void ReadXml(XmlReader reader) 
     { 
      reader.MoveToContent(); 
      var isEmptyElement = reader.IsEmptyElement; 
      reader.ReadStartElement(); 
      if (!isEmptyElement) 
      { 
       Name = reader.ReadElementString("Name"); 

       int intResult; 
       var success = int.TryParse(reader.ReadElementString("Age"), out intResult); 
       if (success) 
       { 
        Age = intResult; 
       } 

       bool boolResult; 
       success = bool.TryParse(reader.ReadElementString("IsContent"), out boolResult); 
       if (success) 
       { 
        IsContent = boolResult; 
       } 
       DateTime dateTimeResult; 
       success = DateTime.TryParseExact(reader.ReadElementString("BirthDay"), "yyyy-MM-dd", null, 
        DateTimeStyles.None, out dateTimeResult); 
       if (success) 
       { 
        BirthDay = dateTimeResult; 
       } 
       reader.ReadEndElement(); //Must Do 
      } 
     } 

     public void WriteXml(XmlWriter writer) 
     { 
      writer.WriteElementString("Name", Name); 
      writer.WriteElementString("Age", Age.ToString()); 
      writer.WriteElementString("IsContent", IsContent.ToString()); 
      writer.WriteElementString("BirthDay", BirthDay.ToString("yyyy-MM-dd")); 
     } 
    } 
} 

第一次:2051813

1000閱讀平均分:208

手卷

public class FoobarHandRolled 
    { 
     public FoobarHandRolled(string name, int age, bool isContent, DateTime birthDay) 
     { 
      Name = name; 
      Age = age; 
      IsContent = isContent; 
      BirthDay = birthDay; 
     } 

     public FoobarHandRolled(string xml) 
     { 
      if (string.IsNullOrWhiteSpace(xml)) 
      { 
       return; 
      } 

      SetName(xml); 
      SetAge(xml); 
      SetIsContent(xml); 
      SetBirthday(xml); 
     } 

     public string Name { get; set; } 
     public int Age { get; set; } 
     public bool IsContent { get; set; } 
     public DateTime BirthDay { get; set; } 

     /// <summary> 
     ///  Takes this object and creates an XML representation. 
     /// </summary> 
     /// <returns>An XML string that represents this object.</returns> 
     public override string ToString() 
     { 
      var builder = new StringBuilder(); 
      builder.Append("<FoobarHandRolled>"); 

      if (!string.IsNullOrWhiteSpace(Name)) 
      { 
       builder.Append("<Name>" + Name + "</Name>"); 
      } 

      builder.Append("<Age>" + Age + "</Age>"); 
      builder.Append("<IsContent>" + IsContent + "</IsContent>"); 
      builder.Append("<BirthDay>" + BirthDay.ToString("yyyy-MM-dd") + "</BirthDay>"); 
      builder.Append("</FoobarHandRolled>"); 

      return builder.ToString(); 
     } 

     private void SetName(string xml) 
     { 
      Name = GetSubString(xml, "<Name>", "</Name>"); 
     } 

     private void SetAge(string xml) 
     { 
      var ageString = GetSubString(xml, "<Age>", "</Age>"); 
      int result; 
      var success = int.TryParse(ageString, out result); 
      if (success) 
      { 
       Age = result; 
      } 
     } 

     private void SetIsContent(string xml) 
     { 
      var isContentString = GetSubString(xml, "<IsContent>", "</IsContent>"); 
      bool result; 
      var success = bool.TryParse(isContentString, out result); 
      if (success) 
      { 
       IsContent = result; 
      } 
     } 

     private void SetBirthday(string xml) 
     { 
      var dateString = GetSubString(xml, "<BirthDay>", "</BirthDay>"); 
      DateTime result; 
      var success = DateTime.TryParseExact(dateString, "yyyy-MM-dd", null, DateTimeStyles.None, out result); 
      if (success) 
      { 
       BirthDay = result; 
      } 
     } 

     private string GetSubString(string xml, string startTag, string endTag) 
     { 
      var startIndex = xml.IndexOf(startTag, StringComparison.Ordinal); 
      if (startIndex < 0) 
      { 
       return null; 
      } 

      startIndex = startIndex + startTag.Length; 

      var endIndex = xml.IndexOf(endTag, StringComparison.Ordinal); 
      if (endIndex < 0) 
      { 
       return null; 
      } 

      return xml.Substring(startIndex, endIndex - startIndex); 
     } 
    } 

第一次:161105

1000閱讀平均分:29

的XElement

 var xDoc = XElement.Parse(xml); 

     var nameElement = xDoc.Element("Name"); 
     var ageElement = xDoc.Element("Age"); 
     var isContentElement = xDoc.Element("IsContent"); 
     var birthDayElement = xDoc.Element("BirthDay"); 

     string name = null; 
     if (nameElement != null) 
     { 
      name = nameElement.Value; 
     } 
     var age = 0; 
     if (ageElement != null) 
     { 
      age = int.Parse(ageElement.Value); 
     } 
     var isContent = false; 
     if (isContentElement != null) 
     { 
      isContent = bool.Parse(isContentElement.Value); 
     } 
     var birthDay = new DateTime(); 
     if (birthDayElement != null) 
     { 
      birthDay = DateTime.ParseExact(birthDayElement.Value, "yyyy-MM-dd", CultureInfo.InvariantCulture); 
     } 

第一次:247024

1000閱讀平均分:113個