![](/img/trans.png)
[英]C# de-serialise Xml to object and serialise back to Xml again
[英]C# fastest way to serialise object to xml string
背景:我的任務是將C#對象序列化為xml字符串。 然后將xml字符串傳遞給webservice,並以xml文件的形式寫入磁盤。 序列化任務需要在該過程獲得的5分鍾內完成。 使用者Web服務僅接受字符串作為xml。 我一直在研究從xml序列化器,xmlwriter,xdocument,stringbuilder編寫xml字符串,對象到json到xml,linq到xml的創建xml字符串的各種方式,但是我需要知道是否有人有做類似事情的經驗。 主要目標是擁有一個高性能的xml字符串,它不像在字符串中創建xml那樣冗長且容易出錯。
我的對象叫Employee,有18個字符串/日期屬性。 這些對象是在內存中創建的,一旦啟動,我們總共可以得到4000k對象。 該過程每天運行1個小時,從數據文件中加載數據並創建人員對象。 在對象上執行許多功能。 對象准備就緒后,需要對其進行序列化,並將xml中的數據發送到webservice並將其寫入xml文件。 簡而言之,這些對象需要序列化並保存到磁盤並發送到Webservice。
有沒有人推薦任何高性能但又容易做到的。 保持方法? 抱歉不放置任何代碼,因為我可以創建一個類並添加xml serialiser等代碼,但由於當前我正在尋找過去的經驗,我不認為此刻會增加任何價值,而且我想確保自己不會過失追逐並想以正確的解決方案實施。
我嘗試了以下序列化程序代碼,但是序列化所有4000k對象需要10分鍾以上的時間。
public static bool Serialize<T>(T value, ref string serializeXml)
{
if (value == null)
{
return false;
}
try
{
XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
StringWriter stringWriter = new StringWriter();
XmlWriter writer = XmlWriter.Create(stringWriter);
xmlserializer.Serialize(writer, value);
serializeXml = stringWriter.ToString();
writer.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
我也嘗試過緩存序列化器,但是沒有任何性能上的改進
根據您的要求,速度是最苛刻的部分。 我們需要在此處編寫一個基准。 如評論中所述,除了XmlSerializer
之外,我們還可以使用DataContractSerializer
來達到目的。 與這兩者之間的區別有關的一些問答,例如:
另一個選擇是使用StringBuilder
或XmlWriter
手動編寫XML。 盡管在要求中您提到:
主要目標是擁有一個高性能的xml字符串,它不像在字符串中創建xml那樣冗長且容易出錯
添加這三個串行器以進行比較。 當然,對於StringBuilder
,必須對文本進行轉義。 在這里,我使用了System.Security.SecurityElement.Escape
。 要序列化的對象如下所示:
//Simple POCO with 11 String properties, 7 DateTime properties
[DataContractAttribute()]
public class Employee
{
[DataMember()]
public string FirstName { set; get; }
[DataMember()]
public string LastName { set; get; }
//...omitted for clarity
[DataMember()]
public DateTime Date03 { set; get; }
[DataMember()]
public DateTime Date04 { set; get; }
}
並且所有屬性都有值(非null),該值在調用序列化程序之前分配。 序列化器代碼如下:
//Serialize using XmlSerializer
public static bool Serialize<T>(T value, ref StringBuilder sb)
{
if (value == null)
return false;
try
{
XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
using (XmlWriter writer = XmlWriter.Create(sb))
{
xmlserializer.Serialize(writer, value);
writer.Close();
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex);
return false;
}
}
//Serialize using DataContractSerializer
public static bool SerializeDataContract<T>(T value, ref StringBuilder sb)
{
if (value == null)
return false;
try
{
DataContractSerializer xmlserializer = new DataContractSerializer(typeof(T));
using (XmlWriter writer = XmlWriter.Create(sb))
{
xmlserializer.WriteObject(writer, value);
writer.Close();
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex);
return false;
}
}
//Serialize using StringBuilder
public static bool SerializeStringBuilder(Employee obj, ref StringBuilder sb)
{
if (obj == null)
return false;
sb.Append(@"<?xml version=""1.0"" encoding=""utf-16""?>");
sb.Append("<Employee>");
sb.Append("<FirstName>");
sb.Append(SecurityElement.Escape(obj.FirstName));
sb.Append("</FirstName>");
//... Omitted for clarity
sb.Append("</Employee>");
return true;
}
//Serialize using XmlSerializer (manually add elements)
public static bool SerializeManual(Employee obj, ref StringBuilder sb)
{
if (obj == null)
return false;
try
{
using (var xtw = XmlWriter.Create(sb))
{
xtw.WriteStartDocument();
xtw.WriteStartElement("Employee");
xtw.WriteStartElement("FirstName");
xtw.WriteString(obj.FirstName);
xtw.WriteEndElement();
//...Omitted for clarity
xtw.WriteEndElement();
xtw.WriteEndDocument();
xtw.Close();
}
return true;
}
catch(Exception ex)
{
Console.WriteLine(ex);
return false;
}
}
在基准測試中,將以4M Employee
對象作為參數,並將XML寫入預分配的StringBuilder
(參數ref StringBuilder sb
)。 對於DataContractSerializer
和Manual XmlWriter
,還執行了Parallel.Invoke
(3個並行任務)的基准測試。 每個序列化程序所需的處理時間:
//Simple POCO with 11 String properties, 7 DateTime properties
XmlSerializer =00:02:37.8151125 = 157 sec: 100% (reference)
DataContractSerializer=00:01:10.3384361 = 70 sec: 45% (3-Parallel: 47sec = 30%)
StringBuilder =00:01:22.5742122 = 82 sec: 52%
Manual XmlWriter =00:00:57.8436860 = 58 sec: 37% (3-Parallel: 40sec = 25%)
環境: .Net Framework 4.5.2, Intel(R) Core(TM) i5-3337U @ 1.80GHz 1.80GHz, Windows 10, 6.0GB Memory
。 我希望StringBuilder
最快,但是不是。 瓶頸可能在System.Security.SecurityElement.Escape()
。
結論: DataContractSerializer
在要求之內,與XmlSerializer
相比,處理時間為30-45%
。 結果可能因環境而異,因此您應該制定自己的基准。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.