根据您的要求,速度是最苛刻的一部分。我们需要在这里写一个基准。正如评论中提到的,除了XmlSerializer
之外,我们可以使用DataContractSerializer
来达到我们的目的。有几个Q &一个相关的这两个之间的区别,例如:
- DataContractSerializer vs XmlSerializer: Pros and Cons of each serializer
- Linq to Xml VS XmlSerializer VS DataContractSerializer
- Difference between DataContractSerializer vs XmlSerializer
另一个选项是使用手动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; }
}
并且所有属性都有值(非空),在调用序列化程序之前分配。该串行代码看起来像:
//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
在要求范围内,处理时间为30-45%
与XmlSerializer
相比较。结果可能因环境而异,您应该制定自己的基准。
为什么你需要它作为字符串?为什么不使用流?另外,缓存你的XmlSerializer实例。它消耗了大量的内存,并且可以重复使用。 – eocron
我试过缓存但没有结果。需要是一个字符串,所以我可以发送到webservice。 – InfoLearner
你不能发送它作为流? – eocron