2008-11-10 30 views
7

Tôi chuyển tài liệu XML nhỏ (2-10 KB) làm đầu vào cho dịch vụ WCF. bây giờ tôi đã hai tùy chọn để đọc các giá trị dữ liệu từ XML đếnXPath vs DeSerialization: cái nào có hiệu suất tốt hơn cho hoạt động đọc

  1. Deserialize đến một đối tượng và đối tượng sử dụng đặc tính mạnh mẽ gõ để truy cập giá trị
  2. sử dụng XPath để giá trị truy cập

mà cách tiếp cận nhanh hơn ? một số thống kê để hỗ trợ câu trả lời của bạn sẽ tuyệt vời.

Trả lời

7

Tôi sẽ deserialize nó.

Nếu bạn sử dụng xpath, bạn sẽ deserialize (hoặc "tải") nó vào XmlDocument hoặc một cái gì đó anyway. Vì vậy, cả hai giải pháp đều sử dụng deserializing thời gian. Sau khi điều này được thực hiện, xpath sẽ chậm hơn do thời gian phân tích cú pháp chuỗi đó, giải quyết tên, chức năng thực thi và vân vân. Ngoài ra, nếu bạn đi với xpath, bạn sẽ không nhận được sự an toàn kiểu nào. Trình biên dịch của bạn không thể kiểm tra cú pháp xpath cho bạn.

Nếu bạn sử dụng XmlSerializer và các lớp, bạn sẽ nhận được gõ tĩnh. Truy cập nhanh vào dữ liệu của bạn và nếu bạn muốn truy vấn chúng bằng xpath, vẫn có nhiều cách để thực hiện điều đó.

Ngoài ra, tôi muốn nói rằng mã của bạn có thể dễ hiểu hơn với các lớp học.

Hạn chế duy nhất là xml phải tuân thủ cùng một giản đồ mọi lúc, nhưng điều đó có thể không phải là vấn đề thực sự trong trường hợp của bạn.

Tôi hy vọng rằng bạn tha thứ cho sự vắng mặt của số liệu thống kê, tôi nghĩ rằng các đối số đủ mạnh mà không có ví dụ. Nếu bạn muốn có câu trả lời cuối cùng, hãy thử cả hai và giữ một đồng hồ bấm giờ sẵn sàng.

+0

Nó không phải là trường hợp sử dụng giống như đã đề cập trên truy vấn, nhưng khi tôi tuần tự hóa/deserialized một lượng lớn dữ liệu khoảng 600 MB, tôi đánh giá cao việc sử dụng IXmlSerializableAttribute. –

4

Có tùy chọn thứ ba gắn bó với XML, nhưng truy vấn với bất kỳ API XML nào bạn đang sử dụng - ví dụ: LINQ to XML làm cho các truy vấn tương đối đơn giản trong mã.

Bạn đã phân tích cú pháp văn bản thành tài liệu XML chưa?

Bạn có tin rằng đây thực sự là một nút cổ chai hiệu suất đáng kể trong mã của bạn? (ví dụ: nếu bạn đang nói chuyện với một cơ sở dữ liệu, thì đừng lo lắng về điều này để bắt đầu - chỉ cần làm cho nó hoạt động theo cách đơn giản nhất trước)

Các truy vấn luôn giống nhau hoặc chúng năng động trong một cách nào đó?

Bạn có giàn khoan thử nghiệm với các thông điệp và truy vấn thực tế không? Nếu không, bạn cần một tài khoản để đánh giá mọi câu trả lời được cung cấp tại đây với dữ liệu của bạn. Nếu bạn làm như vậy, tôi hy vọng sẽ dễ dàng để thử nó một cách hợp lý :)

+0

Cảm ơn Jon, > Bạn đã phân tích cú pháp văn bản thành tài liệu XML chưa? có, tôi nhận được một XMLDocument làm đầu vào > Các truy vấn có luôn giống nhau hoặc chúng có động theo một cách nào đó không? truy vấn luôn giống nhau. Tôi không có dữ liệu thực tế để thử nghiệm, một ý tưởng thô sẽ đủ cho bây giờ –

+0

Tôi đề nghị bạn viết nó theo cách dễ nhất hiện tại (có thể là XPath) và đo thời gian thực hiện cho truy vấn so với hiệu suất của toàn bộ yêu cầu . Nếu tỷ lệ đó trở nên đáng kể, hãy xem lại vấn đề. –

1

Dưới đây là 4 trường hợp, mọi thời điểm trong ve và đặt:

  • XmlSerializer (4 Chậm nhất)
  • thực hiện IXmlSerializable (3)
  • Tay cuộn (Tùy chỉnh) (1st)
  • XElement (2)

Đối tượng mẫu được đọc 1000 lần.

Nếu bạn quan tâm? Đối với đa số trường hợp, sử dụng serializers mặc định được tích hợp vào .net. Không cần phải đi chệch và điều đó sẽ tạo ra số lượng mã tối thiểu. Những thứ đó phải đầy đủ, cung cấp loại an toàn và tự do tự làm những việc có ý nghĩa hơn với thời gian của bạn. Trong một số trường hợp, XElement có thể hữu ích nếu bạn muốn anh đào chọn một số yếu tố dữ liệu nhất định của một cấu trúc XML lớn, nhưng thậm chí sau đó người ta nên đặt những yếu tố đó vào một DTO được đánh máy mạnh mẽ. Nhưng lưu ý, tất cả các phương pháp đều rất nhanh. Cá nhân tôi đã tuần tự hóa một mô hình đối tượng cực rộng và sâu (hơn 400 vòng) chỉ trong vài phần nghìn giây. Đối với các đối tượng nhỏ hơn và tầm thường, nó sẽ là thời gian phản hồi phụ ms. XMLSerializer khởi động chậm hơn so với những người khác, nhưng người ta có thể giảm thiểu với SGEN hoặc thực hiện một số khởi tạo khi khởi động.

Các chi tiết và Mã ...

Xml Serializer

[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; } 
    } 

lần đầu tiên: 2448965

1000 đọc trung bình: 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")); 
     } 
    } 
} 

lần đầu tiên: 2051813

1000 đọc trung bình: 208

tay Rolled

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

lần đầu tiên: 161105

1000 đọc trung bình: 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); 
     } 

First Time: 247024

1000 Đọc trung bình: 113

Các vấn đề liên quan