SYSK 320: Binary vs. xml serialization performance
In my post SYSK 315 (http://blogs.msdn.com/irenak/archive/2007/03/27/sysk-315-generic-functions-for-object-xml-serialization-deserialization.aspx) I shared two generic functions for serialization and de-serialization of any object to/from xml.
Reader Doug was wondering on the performance of those methods. So, here is my response:
On my Toshiba Tecra M5 (dual 2Ghz processor, 2Gb memory) an object of type List<object[]> containing 296 “rows” and 18 “columns” with elements of different data types (strings, integers, dates, etc.) takes approximately 14 ms per iteration for binary serialization & de-serialization and 31 ms per iteration for xml serialization & de-serialization.
Summary: My tests show that, on average, xml serialization is roughly twice that of binary serialization (i.e. binary serialization takes half the time compared to xml serialization).
Note: Serialization performance depends on the complexity of the object, so you should do your own tests to get more precise results for your situation.
******************************************************************
Here is the code I used:
private void button1_Click(object sender, EventArgs e)
{
List<object[]> data = new List<object[]>();
using (System.Data.SqlClient.SqlConnection cn = new System.Data.SqlClient.SqlConnection("Persist Security Info=False;Integrated Security=SSPI;database=AdventureWorks;server=(local);"))
{
cn.Open();
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(
"select E.EmployeeID, E.NationalIDNUmber, E.LoginID, E.Title, E.ManagerID, E.BirthDate, E.MaritalStatus, E.Gender," +
"E.HireDate, E.SalariedFlag, E.VacationHours, E.SickLeaveHours, " +
"D.Name, D.GroupName, A.AddressLine1, A.AddressLine2, A.City, A.PostalCode " +
"from HumanResources.Employee E " +
"inner join HumanResources.EmployeeDepartmentHistory ED on ED.EmployeeID = E.EmployeeID " +
"inner join HumanResources.Department D on ED.DepartmentID = D.DepartmentID " +
"inner join HumanResources.EmployeeAddress EA on E.EmployeeID = EA.EmployeeID " +
"inner join Person.Address A on EA.AddressID = A.AddressID " +
"where E.CurrentFlag = 1",
cn);
using (System.Data.SqlClient.SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
object[] row = new object[dr.FieldCount];
dr.GetValues(row);
data.Add(row);
}
}
}
// Replace DBNull
foreach (object[] row in data)
{
for (int i = 0; i < row.Length; i++)
{
if (row[i] is DBNull)
{
row[i] = null;
}
}
}
System.Diagnostics.Stopwatch swXml = new System.Diagnostics.Stopwatch();
System.Diagnostics.Stopwatch swBinary = new System.Diagnostics.Stopwatch();
for (int i = 0; i < 500; i++)
{
swXml.Start();
string xml = ToXml<List<object[]>>(data);
List<object[]> fromXml = FromXml<List<object[]>>(xml);
swXml.Stop();
swBinary.Start();
string binary = ToBinary<List<object[]>>(data);
List<object[]> fromBinary = FromBinary<List<object[]>>(binary);
swBinary.Stop();
}
System.Diagnostics.Debug.WriteLine(string.Format("Xml serialization: {0} ms", swXml.ElapsedMilliseconds));
System.Diagnostics.Debug.WriteLine(string.Format("Binary serialization: {0} ms", swBinary.ElapsedMilliseconds));
}
public static string ToXml<T>(T source)
{
string result = null;
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
using (System.Xml.XmlWriter writer = System.Xml.XmlTextWriter.Create(sw, null))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
serializer.Serialize(writer, source);
}
result = sw.ToString();
}
return result;
}
public static T FromXml<T>(string xml)
{
T result = default(T);
if (string.IsNullOrEmpty(xml) == false)
{
using (System.IO.StringReader sr = new System.IO.StringReader(xml))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
result = (T)serializer.Deserialize(sr);
}
}
return result;
}
public static string ToBinary<T>(T source)
{
string result = null;
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
formatter.Serialize(ms, source);
ms.Position = 0;
byte[] data = ms.GetBuffer();
result = System.Text.UnicodeEncoding.Default.GetString(data);
}
return result;
}
public static T FromBinary<T>(string data)
{
T result = default(T);
if (string.IsNullOrEmpty(data) == false)
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(System.Text.UnicodeEncoding.Default.GetBytes(data)))
{
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
result = (T) formatter.Deserialize(ms);
}
}
return result;
}