Comparing C# Serialization Techniques: Be wary of XMLMorgan KenyonBlockedUnblockFollowFollowingJun 17Photo by NASA on UnsplashIf you do any type of web programming, serialization is something that constantly happens.
Any time data needs is converted between a language specific class and some other format, serialization occurs.
And that is a costly operation.
For most applications, serialization is a cost that is worth the benefits.
It’s slow, but it’s useful and makes development easier.
In my career I’ve worked with both Json and Xml on different projects and I never knew which one was faster.
So I decided to write a benchmark to test it out.
We will be testing 2 json, 3 xml and 1 protobuf-net method.
Each benchmark will read in a file containing the text for each serialization type.
Then access every element in the class.
Each test is remarkably similar, so I’m only going to show a regular json to C# example.
Every example is on the github library if you’re interested in exploring futher.
Json TestingI’m starting with the following json string generated from this website.
Which I’ve saved to a file, then for the test it performs the following steps:De-serializesVisits every propertySerializesThe only difference between all the methods is that Probobuf-net uses streams when deserializing/serializing and json and xml uses with strings.
I don’t think that significantly changes the benchmark, but something to note.
Different MethodsSo I’m testing a total of 6 different ways to deserialize/serialize data:JsonToObjectTest — testing serializing json string to JObject.
JsonToObjectTest — testing serializing json string to C# class.
XmlToObjectTest — testing serializing xml string to C# class, with a new serializer every time.
XmlPrepTimeIncludedTest — testing serializing xml string to C# class, with the shared serializer included in timing of test.
XmlPrepTimeExcludedTest — testing serializing xml string to C# class, with the shared serializer not included in the timing of the tests.
ProtoBufToObjectTest — testing protobuf streams to C# class.
I’ll explain more about the 3 different xml tests, but I ran into some performance issues and wanted to drill down a bit into why xml performance was so bad.
ResultsLaunching this benchmark from the console results in the following statistics.
Performance ResultsThe first thing that jumps out to me is what is heck is wrong with XMLToObject!.It’s performance is about 1000x worse than JsonToObject or ProtoBufToObject!When I first saw these results I didn’t believe them!.I didn’t think that could be that much slower.
So I had to investigate.
XML IssuesSo XML has some issues.
At first I was baffled, I couldn’t wrap my mind around it.
So I did some research and eventually discovered this stackoverflow question/answer.
XmlSerializer – the first deserialization is very slowI have a solution with two projects; an asp.
net MVC application, and a class library.
Let's call them project MVC and…stackoverflow.
comWhen you instantiate an XmlSerializer you have to pass the Type of the objects that you will attempt to serialize and deserialize with that serializer instance.
The serializer examines all public fields and properties of the Type to learn about which types an instance references at runtime.
It then proceeds to create C# code for a set of classes to handle serialization and deserialization using the classes in the System.
CodeDOM namespace.
During this process, the XmlSerializer checks the reflected type for XML serialization attributes to customize the created classes to the XML format definition.
These classes are then compiled into a temporary assembly and called by the Serialize() and Deserialize() methods to perform the XML to object conversions.
So basically there’s a one time initialization cost to using XmlSerializer.
In the worst performing test, I was creating a new instance every time.
Which was the reason for the terrible performance.
The two others shared the same XmlSerializer in their benchmarks.
Which is why their performance was so much better.
The only difference being the XmlPrepTimeIncludedTest included the initial XmlSerializer creation in the benchmark timing.
While the XmlPrepTimeExcludedTest did not.
TakeawaysSo what can we take a way from this benchmark?.Because serialization is such a costly operation, you shouldn’t use it blindly.
Subtle differences can lead to drastic performance differences, especially with XML.
After using C# professionally for four years, this is the first time I’ve heard of this XML problem.
Thinking about using XML in the past I’ve definitely written code that had this performance problem and I had no idea.
And lastly, use benchmarks to find out what performance issues your code has.
Don’t assume if you got something off stackoverflow or patterns already exists in your app that they’re performant.
I’m Morgan Kenyon.
I’m a .
NET developer working in the DFW area.
I find C# a great language to use and it’s also backed by a great ecosystem, I love solving hard problems and want to continue talking about the tech I use.
If you found this article helpful or thought provoking leave a comment and lets connect over LinkedIn!Github Repo.. More details