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;

}