9 minute read

One of the hot topics of discussion in building enterprise applications is whether one should use JSON or XML based serialization for

  • data serialization and deserialization
  • data storage
  • data transfer

To illustrate these aspects, let’s write some code that can help build the facts.  Our code will involve creating an entity User

  1. public class User
  2. {
  3.     public string Name { get; set; }
  4.     public int Id { get; set; }
  5.     public UserType Type { get; set; }
  6. }
  7.  
  8. public enum UserType { Tech, Business, Support }

 

To test performance and other criteria we will use standard XML serialization, and for JSON we will evaluate these parameters using 2 open source frameworks Newtonsoft.Json and ServiceStack.Text

To create dummy data, our code looks like

 

  1. private Random rand = new Random();
  2. private char[] letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
  3.  
  4. private List<User> GetDummyUsers(int max)
  5. {
  6.     var users = new List<User>(max);
  7.     for (int i = 0; i < max; i++)
  8.     {
  9.         users.Add(new User { Id = i, Name = GetRandomName(), Type = UserType.Business });
  10.     }
  11.  
  12.     return users;
  13. }
  14.  
  15. private string GetRandomName()
  16. {
  17.     int maxLength = rand.Next(1, 50);
  18.     string name = string.Empty;
  19.     for (int i = 0; i < maxLength; i++)
  20.     {
  21.         name += letters[rand.Next(26)];
  22.     }
  23.     return name;
  24. }
  25.  
  26. private long Compress(byte[] data)
  27. {
  28.     using (var output = new MemoryStream())
  29.     {
  30.         using (var compressor = new GZipStream(output, CompressionMode.Compress, true))
  31.         using (var buffer = new BufferedStream(compressor, data.Length))
  32.         {
  33.             for (int i = 0; i < data.Length; i++)
  34.                 buffer.WriteByte(data[i]);
  35.         }
  36.         return output.Length;
  37.     }
  38. }

 

The serialization logic to convert List<User> to serialized string and gather the statistics is

 

  1. public void Experiment()
  2. {
  3.     DateTime dtStart = DateTime.Now;
  4.     List<User> users = GetDummyUsers(20000); // change the number here
  5.     Console.WriteLine("Data generation  \t\t took mSec: "
  6.         + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  7.  
  8.     Console.WriteLine("----");
  9.  
  10.     dtStart = DateTime.Now;
  11.     var xml = MyXmlSerializer.Serialize<List<User>>(users, Encoding.UTF8);
  12.     Console.WriteLine("Length (XML):      \t" + xml.Length + " took mSec: "
  13.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  14.     xml = MyXmlSerializer.Serialize<List<User>>(users, Encoding.UTF8);
  15.     Console.WriteLine("Length (XML):      \t" + xml.Length + " took mSec: "
  16.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  17.  
  18.     dtStart = DateTime.Now;
  19.     var json = JsonConvert.SerializeObject(users);
  20.     Console.WriteLine("Length (JSON.NET): \t" + json.Length + " took mSec: "
  21.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  22.     dtStart = DateTime.Now;
  23.     json = JsonConvert.SerializeObject(users);
  24.     Console.WriteLine("Length (JSON.NET): \t" + json.Length + " took mSec: "
  25.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  26.  
  27.     var serializer2 = new JsvSerializer<List<User>>();
  28.     dtStart = DateTime.Now;
  29.     var json2 = serializer2.SerializeToString(users);
  30.     Console.WriteLine("Length (JSON/ST) : \t" + json2.Length + " took mSec: "
  31.         + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  32.     dtStart = DateTime.Now;
  33.     json2 = serializer2.SerializeToString(users);
  34.     Console.WriteLine("Length (JSON/ST) : \t" + json2.Length + " took mSec: "
  35.         + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  36.  
  37.     Console.WriteLine("----");
  38.     
  39.     var xmlBytes = Converter.ToByte(xml);
  40.     Console.WriteLine("Bytes (XML):     \t" + xmlBytes.Length);
  41.  
  42.     var jsonBytes = Converter.ToByte(json);
  43.     Console.WriteLine("Bytes (JSON):    \t" + jsonBytes.Length);
  44.  
  45.     var jsonBytes2 = Converter.ToByte(json);
  46.     Console.WriteLine("Bytes (JSON/ST): \t" + jsonBytes2.Length);
  47.  
  48.     Console.WriteLine("----");
  49.  
  50.     var compressedBytes = Compress(xmlBytes);
  51.     Console.WriteLine("Compressed Bytes (XML):     \t" + compressedBytes);
  52.  
  53.     compressedBytes = Compress(jsonBytes);
  54.     Console.WriteLine("Compressed Bytes (JSON):    \t" + compressedBytes);
  55.  
  56.     compressedBytes = Compress(jsonBytes2);
  57.     Console.WriteLine("Compressed Bytes (JSON/ST): \t" + compressedBytes);
  58.  
  59.     Console.WriteLine("----");
  60.  
  61.     dtStart = DateTime.Now;
  62.     MyXmlSerializer.Deserialize<List<User>>(xml, Encoding.UTF8);
  63.     Console.WriteLine("Deserialized (XML): \t took mSec "
  64.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  65.     MyXmlSerializer.Deserialize<List<User>>(xml, Encoding.UTF8);
  66.     Console.WriteLine("Deserialized (XML): \t took mSec "
  67.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  68.  
  69.     dtStart = DateTime.Now;
  70.     JsonConvert.DeserializeObject<List<User>>(json);
  71.     Console.WriteLine("Deserialized (JSON): \t took mSec "
  72.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  73.     dtStart = DateTime.Now;
  74.     JsonConvert.DeserializeObject<List<User>>(json);
  75.     Console.WriteLine("Deserialized (JSON): \t took mSec "
  76.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  77.  
  78.     dtStart = DateTime.Now;
  79.     serializer2.DeserializeFromString(json2);
  80.     Console.WriteLine("Deserialized (JSON/ST): \t took mSec "
  81.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  82.     serializer2.DeserializeFromString(json2);
  83.     Console.WriteLine("Deserialized (JSON/ST): \t took mSec  "
  84.             + DateTime.Now.Subtract(dtStart).TotalMilliseconds);
  85.  
  86. }

Statistics

On running this program on a Quad-Core processor with 6 GB RAM, the statistics look as below. 

 

image

 

What the statistics mean?

 

  • Serialization and Deserialization Performance

    For XML Serialization, there is no decrease in serialization time in the subsequent serialization requests even after using the same XmlSerializer object.  When using JSON, we see that the frameworks reduce the serialization time drastically.  JSON serialization appears to give us an gain of 50-97% in serialization time. 

    When dealing with deserialization, XML deserialization gives a better performance consistently with both data sets (20K and 200K).  JSON deserialization seems to take more time even when averaged. 

    Every application requires both serialization and deserialization features.  Considering the performance statistics, it looks like using ServiceStack.Text outperforms other two libraries. 

    Winner: JSON with ServiceStack.Text by taking 91% of time taken by Xml serialization + deserialization

  • Data Storage

    Looking at data storage aspect, Xml based string definitely requires more storage space.  So if you are looking at storing string, JSON is the clear choice at benefit.

    However, when you apply GZip compression on serialized strings generated by XML / JSON frameworks it appears that there is no major difference in the storage size.  JSON still saves some bytes for you!  This is one reason some NoSQL databases uses JSON based storage instead of XML based storage.  However, for quicker retrieval you need to apply some indexing mechanisms too.

    Winner: JSON without compression; With compression, minor gain by using JSON

  • Data Transfer

    Data transfer comes in picture when you are transferring your objects on EMS / MQ / WebServices.  Keeping other parameters such as network latency, availability, bandwidth, throughput, etc. as constants in both cases amount of data transfer becomes a function of data length or protocol used over network. 

    For EMS / MQ – Data length, as in statistics, is lesser in case of JSON when sent as string and almost same when sending as compressed bytes. 

    For WebServices / WCF – Data transfer depends on the protocol used.  If you are using SOAP based services, apart from your serialized Xml you will also have SOAP headers that will form the payload.  But if you are using REST protocol, you can return plain Xml / JSON and in that case a JSON string will have lesser payload than XML string.

    Winner: Depends on the protocol of transfer and compression technique used

 

Note: The performance may vary slightly when using any other C# libraries. But, hopefully, the % change should be neutralized.

 

Hope this article helps you to choose the right protocol and technique for your application.  If you have any questions, I’ll be happy to help you!