Skip to content


Performance oriented Xml and JSON serialization in .NET

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Microsoft .NET framework provides multiple out-of-the-box data serializers for data transformations.  The most famous one used since .NET 1.0 version is XmlSerializer, while one that has got more famous since .NET 3.0 framework is DataContractSerializer.   But they are not the only two serializers the framework offers.  So in this essay, let’s see the different serializers .NET framework offers and how they are different from each other.  So here’s the list of serializers

  • XmlSerializer: The most commonly used xml serializer
  • JavaScriptSerializer:  Introduced in ASP.NET Ajax Extensions in .NET 2.0, and now marked as obsolete, primarily provided JSON serializer
  • DataContractSerializer: Introduced in .NET 3.0 with Windows Communication Foundation (WCF), this is default serializer in WCF.
  • NetDataContractSerializer: A not-too-famous serializer that includes CLR type information in serialized xml which DataContractSerializer does not.
  • DataContractJsonSerializer:  Introduced in .NET 3.5, this class is handy in generating JSON output of an entity

Next, let’s define a class Employee and implement a serializer class and try out XmlSerializer, DataContractSerializer, NetDataContractSerializer and DataContractJsonSerializer with examples.

Step 1- Defining Employee class

The structure of Employee class is different for different serializers.  So make a note that XmlSerializer requires a parameterless or a default constructor, while other serializers do not require so.  Other serialisers based on DataContractSerializer require DataContract and DataMember attribute on the class and its members, while XmlSerializer requires either a native type, or ISerizable implemented complex class (read: class)

Employee Class
  1. ///<summary>
  2. /// Employee class for all other serializers
  3. ///</summary>
  4. [DataContract]
  5. public class Employee
  6. {
  7.     [DataMember]
  8.     public string Name { get; set; }
  9.     [DataMember]
  10.     public int EmployeeId { get; set; }
  11.     ///<summary>
  12.     /// Note: Default constructor is not mandatory
  13.     ///</summary>
  14.     public Employee(string name, int employeeId)
  15.     {
  16.         this.Name = name;
  17.         this.EmployeeId = employeeId;
  18.     }
  19. }
  20. ///<summary>
  21. /// Employee class for XmlSerializer
  22. ///</summary>
  23. public class Employee
  24. {
  25.     public string Name { get; set; }
  26.     public int EmployeeId { get; set; }
  27.     ///<summary>
  28.     /// Parameter-less constructor is mandatory
  29.     ///</summary>
  30.     public Employee() { }
  31.     public Employee(string name, int employeeId)
  32.     {
  33.         this.Name = name;
  34.         this.EmployeeId = employeeId;
  35.     }
  36. }

Step 2 – Defining the Serialization Factory

To define the serialization factory, we will define an enum SerializerType, and a factory class SerializerFactory and add reference to System.Runtime.Serialization using “Add Reference” option

SerializerType
  1. public enum SerializerType
  2.     {
  3.         ///<summary>
  4.         /// XmlSerializer
  5.         ///</summary>
  6.         Xml,
  7.         ///<summary>
  8.         /// DataContractJsonSerializer
  9.         ///</summary>
  10.         JSON,
  11.         ///<summary>
  12.         /// DataContractSerializer
  13.         ///</summary>
  14.         WCF,
  15.         ///<summary>
  16.         /// NetDataContractSerializer
  17.         ///</summary>
  18.         CLR
  19.     }

The factory class could be plain vanilla object creation based on the enum (SerializerType) value, however creation of serialization object is heavy on performance. Hence, we would like to cache it in the memory for re-use.  So the factory class has been optimized for better performance using a Dictionary of serializers.

Serialization Factory
  1. public static class SerializerFactory
  2.     {
  3.         private static Dictionary<Type, Dictionary<SerializerType, object>> _knownObjects;
  4.         static SerializerFactory()
  5.         {
  6.             _knownObjects = new Dictionary<Type, Dictionary<SerializerType, object>>();
  7.         }
  8.         internal static ISerializer<T1> Create<T1>(SerializerType serializerType)
  9.         {
  10.             Type type = typeof(T1);
  11.             if (_knownObjects.ContainsKey(type))
  12.             {
  13.                 if (_knownObjects[type].ContainsKey(serializerType))
  14.                     return ((ISerializer<T1>)_knownObjects[type][serializerType]);
  15.             }
  16.             ISerializer<T1> returnValue = null;
  17.             switch (serializerType)
  18.             {
  19.                 case SerializerType.Xml:
  20.                     returnValue = new XmlSerializer<T1>();
  21.                     break;
  22.                 case SerializerType.JSON:
  23.                     returnValue = new JsonSerializer<T1>();
  24.                     break;
  25.                 case SerializerType.WCF:
  26.                     returnValue = new WcfSerializer<T1>();
  27.                     break;
  28.                 case SerializerType.CLR:
  29.                     returnValue = new ClrSerializer<T1>();
  30.                     break;
  31.                 default:
  32.                     throw new NotSupportedException(“Unknown serializer type”);
  33.                     break;
  34.             }
  35.             if (_knownObjects.ContainsKey(type) == false)
  36.                 _knownObjects.Add(type, new Dictionary<SerializerType, object>());
  37.             _knownObjects[type].Add(serializerType, returnValue);
  38.             return returnValue;
  39.         }
  40.     }

 

Step 3 – The Main Program (consuming application)

Our main program should be able to support serialization of Employee class, or a list of employee class as shown below:

Main Program
  1. class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             List<Employee> employees = new List<Employee>()
  6.             {
  7.                 new Employee(“Tim”, 1392902),
  8.                 new Employee(“Shawn”, 156902),
  9.             };
  10.             ISerializer<List<Employee>> xmlSerializer = SerializerFactory.Create<List<Employee>>(SerializerType.Xml);
  11.             string xml = xmlSerializer.Serialize(employees);
  12.             ISerializer<List<Employee>> jsonSerializer = SerializerFactory.Create<List<Employee>>(SerializerType.JSON);
  13.             string json = jsonSerializer.Serialize(employees);
  14.             ISerializer<List<Employee>> clrSerializer = SerializerFactory.Create<List<Employee>>(SerializerType.CLR);
  15.             string clr = clrSerializer.Serialize(employees);
  16.             ISerializer<List<Employee>> wcfSerializer = SerializerFactory.Create<List<Employee>>(SerializerType.WCF);
  17.             string wcf = wcfSerializer.Serialize(employees);
  18.             Console.ReadKey();
  19.         }
  20.     }

 

Step 4 – The Serializer implementations

To make this essay shorter and easy to comprehend, only two implementations have been mentioned here: Xml and JSON serializer.  The other two have been included in the source code.

Implementing XmlSerializer

As mentioned earlier, the Xml Serializer requires a default constructor without which the program will throw a runtime exception.

Implementation: XmlSerializer
  1. public class XmlSerializer<T> : ISerializer<T>
  2.     {
  3.         System.Xml.Serialization.XmlSerializer _xmlSerializer =
  4.             new System.Xml.Serialization.XmlSerializer(typeof(T));
  5.         public string Serialize(T value)
  6.         {
  7.             MemoryStream memoryStream = new MemoryStream();
  8.             XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
  9.             _xmlSerializer.Serialize(xmlTextWriter, value);
  10.             memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
  11.             return memoryStream.ToArray().ToStringValue();
  12.         }
  13.         public T Deserialize(string value)
  14.         {
  15.             MemoryStream memoryStream = new MemoryStream(value.ToByteArray());
  16.             XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
  17.             return (T)_xmlSerializer.Deserialize(memoryStream);
  18.         }
  19.     }

 

Implementing JSON Serializer

A Json Serializer is very handy serializer specially when dealing with REST services, or JavaScript, or cross-platform messaging applications.  In recent times, JSON has gained more adoptability considering the ease to understand the serialized output and the cleanliness

Implementation:JSON Serializer
  1. public class JsonSerializer<T> : ISerializer<T>
  2.     {
  3.         DataContractJsonSerializer _jsonSerializer = new DataContractJsonSerializer(typeof(T));
  4.         public string Serialize(T value)
  5.         {
  6.             MemoryStream ms = new MemoryStream();
  7.             _jsonSerializer.WriteObject(ms, value);
  8.             string retVal = ms.ToArray().ToStringValue();
  9.             ms.Dispose();
  10.             return retVal;
  11.         }
  12.         public T Deserialize(string value)
  13.         {
  14.             MemoryStream ms = new MemoryStream(value.ToByteArray());
  15.             T obj = (T)_jsonSerializer.ReadObject(ms);
  16.             ms.Close();
  17.             ms.Dispose();
  18.             return obj;
  19.         }
  20.     }

 

Step 5 – Comparing the serialization results

XmlSerializer

<?xml version=”1.0″ encoding=”utf-8″?>
<ArrayOfEmployee xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>
<Employee>
<Name>Tim</Name>
<EmployeeId>1392902</EmployeeId>
</Employee>
<Employee>
<Name>Shawn</Name>
<EmployeeId>156902</EmployeeId>
</Employee>
</ArrayOfEmployee>

A default schema/namespace defined by w3.org is added in the root node and the collection is named as ArrayOfEmployee. The output is always a valid Xml.

DataContractJsonSerializer

[
{"EmployeeId":1392902,"Name":"Tim"},

{"EmployeeId":156902,"Name":"Shawn"}

]

There is no schema added to the serialized string and the string is more clean and readable.  Items are grouped by parenthesis { } and the collection is encapsulated within Box brackets [ ]

DataContractSerializer

<ArrayOfEmployee xmlns=”http://schemas.datacontract.org/2004/07/Serializers” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance”>
<Employee>
<EmployeeId>1392902</EmployeeId>
<Name>Tim</Name>
</Employee>
<Employee>
<EmployeeId>156902</EmployeeId>
<Name>Shawn</Name>
</Employee>
</ArrayOfEmployee>

A default schema/namespace defined by Microsoft and w3.org is added in the root node and the collection is named as ArrayOfEmployee. The output is always a valid Xml.

NetDataContractSerializer

<ArrayOfEmployee z:Id=”1″ z:Type=”System.Collections.Generic.List`1[[Serializers.Employee, Serializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]” z:Assembly=”0″ xmlns=”http://schemas.datacontract.org/2004/07/Serializers” xmlns:i=”http://www.w3.org/2001/XMLSchema-instance” xmlns:z=”http://schemas.microsoft.com/2003/10/Serialization/”>
<_items z:Id=”2″ z:Size=”4″>
<Employee z:Id=”3″>
<EmployeeId>1392902</EmployeeId>
<Name z:Id=”4″>Tim</Name>
</Employee>
<Employee z:Id=”5″>
<EmployeeId>156902</EmployeeId>
<Name z:Id=”6″>Shawn</Name>
</Employee>
<Employee i:nil=”true”/>
<Employee i:nil=”true”/>
</_items>
<_size>2</_size>
<_version>2</_version>
</ArrayOfEmployee>

A default schema/namespace defined by Microsoft and w3.org is added in the root node and the collection is named as ArrayOfEmployee. The output is always a valid Xml, however the Xml nodes also define CLR metadata such as Type, Size, Version, Id, etc.

[Updated] Performance benchmarks

I modified the example to add 200K employees to the collection to benchmark the performance results.  For the first time, serialization took more time as the serialization object was not cached, but for the subsequent times there was 17-44% improvement in the performance.

XmlSerializer (1): Time to executed 1142.0654 mSec
XmlSerializer (2): Time to executed 635.0364 mSec

DataContractJsonSerializer (1): Time to executed 847.0484 mSec
DataContractJsonSerializer (2): Time to executed 611.0349 mSec
CLR (1): Time to executed 2179.1246 mSec
CLR (2): Time to executed 1914.1095 mSec
DataContractSerializer (1): Time to executed 539.0308 mSec
DataContractSerializer (2): Time to executed 413.0236 mSec
What is worth noticing is the that DataContractSerializer is the fastest serializer, followed by DataContractJsonSerializer and XmlSerializer.  Unless absolutely required NetDataContractSerializer should not be used.

I hope this essay helps in understanding serializers better!

Download the source code [serializers.zip] from SkyDrive


Related Posts:

Posted in C#.

Tagged with , , , .


Silverlight Best Practices (Part 2 of 4)

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

This is in continuation to my previous post Silverlight Best Practices – I, where I talked about Design Considerations.  These design considerations were a bird’s view and the posts to come will explain these in detail.  In this post, I shall deal with the Business Layer, its components, steps to design these components, and design considerations.  This post can be considered not just for Silverlight Applications, but for other Web Applications as well.

Business Layer

 

Let us take on the parts of the business layer for those who are newbie

  1. Application Façade – layer that combines multiple business operations into single message based operation
  2. Business Components – Business Rules & Validations
  3. Entities – Used to pass data between business components
  4. Business Workflow – Multi-step and/or long-running business process

Design Considerations

 

Before you jump into designing of business layer, it is advisable to do these

 

  1. Identify ACTORS or CONSUMERS
  2. How these ACTORS will communicate to your business layer.
    1.  Concurrency needs to be addressed for access to STATIC data.
    2.  Long-running transactions should not LOCK the data.
  3. SECURITY requirements for business layer
    1.  Apply AUTHENTICATION wherever required.
    2. Use SSO where appropriate.
  4.  VALIDATION and EXCEPTION HANDLING strategies
    1. DONOT RELY on validations at presentation layer – reuse the VALIDATION logic.
    2. Should NOT reveal sensitive information to the end user.
    3.  Should NOT use exceptions for application logic.
    4.  Log SUFFICIENT detail from exceptions.

Authentication & Authorization Module Design

Authentication is not a mandate requirement and should be done if the Business Layer is to be used by several clients.  An easier said – public web services need authentication, but an application oriented service does not.

Consider IP filtering to restrict hacks and unauthorized usage or to have access only through the presentation layer.

For business decisions –role based or claim based authorization needs to be implemented.

Impersonation can screw-up your performance. So prefer avoiding it.

Business Components & Entities

Keep them light and encapsulated.  Do not mix data access logic and business logic. Break them into two assemblies. Volatile business rules ought to be kept in rules engine (Workflow, DROOLS.NET, etc)

Use ONLY CUSTOM objects as Business Entities, even if it means encapsulating only a string object.

Choose between the three patterns while designing these entities-

  • Table Module Pattern – this is typically used when database tables can represent entities.  This model is suited for large database applications or applications that use LINQ to SQL.
  • Domain Module Patter – this pattern is widely used for stateful application that has complex business rules.
  • XML – this is used for relatively smaller applications.

Serialize your objects if it requires passing between network boundaries.


Caching and Concurrency

Appropriate caching mechanism can speed up your performance by leaps and bounds by avoiding duplicate processing.  To avoid client delays, caching should be a background process.

Cache the data (non-sensitive ONLY) in a ready-to-use format.  In other words, data taken from cache should not necessarily require processing before use.  Caching resources should avoid locks due to threading.

Use connection based transactions to access single data source. Which means – a rollback should let you get back to previous state. When a rollback or commit cannot be applied (for processes that are long-running), then compensating methods should be in place. 

Logging and Audit Mechanism

Logging and Auditing cannot be compromised at an enterprise level application.  It can open doors to threats without getting noticed.  Auditing, if generated at granular level, can let us know precise time, IP, location of resource access.

One can use Enterprise Library or any other component to implement logging mechanism – but it needs to be centralized.   However unexpected failure of this centralized block should not cause stop the business functionalities.

Workflows

 

Windows Workflow is a great-gift by Microsoft to the technologies. Workflows – state machine or sequential – should be initiated on a separate thread for long-running process.  Faulty conditions should be handled as exceptions. 

Deployment

Towards the end, an incorrect deployment will surely not deliver excellent results. Use TCP protocol and SSL to support remote business layer in a safe manner.

 

The next to come in this series will be a post on what not to do in Silverlight while developing an application. This will focus on best practices that a developer needs to take care of.

 


Related Posts:

Posted in Microsoft .NET, Silverlight.

Tagged with , .


Silverlight Best Practices (Part 3 of 4)

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

[Republished after additions]

This is in continuation to my previous post Silverlight Best Practices – II, where I talked about Business Layer Design Considerations.  This post, the area of concentration, will be a list of to-do’s while developing a Silverlight Application.

Development Tactics and Practices

Defacing Errors

One of the regular application development exercise is debugging and debugging errors in Silverlight applications can be really tough job if your default browser is Chrome. I’m not sure whether there is problem with Chrome, or with Silverlight IDE, or something else – but until today, the breakpoint will not be hit in Chrome. Hence, prefer using Internet Explorer.

Using Team Foundation Servers (TFS)

Silverlight developers often struggle setting up a source-safe (read TFS) within a team. To enable TFS, install VS 2010 and Silverlight Tools on Team Build Server machine.

First-class rule

Ideally, for a file Page.xaml, the first class definition in the Page.xaml.cs should be Page class.  This otherwise has known issues related to code refactoring.

Locally defined StaticResource fails to load

When a StaticResource object is both defined and referenced inside the same element, the Preview Window will fail to load with an error “The type StaticResource was not found.”

Hence, it is advisable to keep Static Resources in App.xaml file. This also helps usage of these resources across the modules in the application.

Share a Brush than copying it

Instead of defining Brush in XAML, define it as StaticResouce and reference it. This creates only one instance and then reuses it.

A Generic TODO list

This is more of a compilation of single-liners that aptly fit in the TODO list of a Silverlight developer.

  • Naming Convention – Casing:
    • Pascal Casing and not Camel Casing is preferred (unlike in C#). myButton is wrong in Silverlight though it is correct in C#. The correct version is MyButton.
    • Use x:Name instead of Name as x:Name is generic and can be used for all elements.
  • Indentation:
    • Place first attribute in-line with the element name like.

<StackPanel  DockPanel.Dock=”Top” Orientation=”Horizontal”>

  • Choose a StaticResource over DynamicResource. For further read, click here
  • Resources should be placed at one location, preferably at Application Level in App.xaml file. This will avoid reloading of resources over and again when objects are created and destroyed.
  • SnapsToDevicePixels – Using graphic objects can appear nice on some monitors, while it may fade on others.  It is preferred to use a Style resource in such scenarios. For more read, click here
  • Define a definite folder structure before starting application development
    • Services – to have WCF service references
    • Images – to store application images and videos
    • Resources – platform specific APIs
    • Data – to store XML, text files
  • Remove the Object Handlers when not in use.  Not removing object handlers may keep the object alive, which may degrade the performance. RegisterClassHandler is called on every instance of object creation, which may cause performance problems
  • Frozen objects over Non-frozen:
    • Frozen objects occupy lesser memory space and are fast in execution.
    • Consider the example on MSDN-  Prefer VirtualizingStackPanel (40mSec) over a simple StackPanel (takes 3000mSec for same UI) to speed up the execution time.
    • Avoid using a TextBlock in FlowDocument
    • Since Label.Content property is slow in execution, TextBlock.Text should be used. (This is one reason why Label is not a part of Silverlight framework, and it is part of WPF)
    • Show underline in Hyperlink only on MouseOver events.  TextDecoration is performance intensive.
    • Bind an IList to an object, not an IEnumerable to avoid an automatic wrapper creation.  This will enhance your performance.
  • Proper node at proper place:
    • While the tree is developed, there can be two approaches – bottom-up or top-down. A top-down approach is 10 times faster. This is because when a node is added or removed from the logical tree, property invalidations are raised on the node’s parent and all its children.

Best practices generally evolve as a result of implementations and errors/observations. So this post remains unconcluded for the users to add in their inputs and make it extensive guide. Keep adding to it

Note: The next in this series is the Data Access Layer Guidelines.


Related Posts:

Posted in Microsoft .NET, Silverlight.

Tagged with , .