Performance Comparison of JSON Serializers for .NET

Json in .NET can be used for a variety of purposes. In my case, this is the formation of an answer to an Ajax request in an ASP.NET Mvc application. Of course, converting the response into JSON is not the thinnest place, but I was wondering how to speed up this operation. This article is not a detailed overview of existing JSON serializers for .NET / Mono. First of all, I was interested in the time spent on serializing relatively simple data structures, and secondly, mapping. That is, I want serialization to be easily and flexibly programmed and work quickly.

The following serialization tools fell into the study:
  1. Simple string concatenation
  2. JavaScriptSerializer (.NET Framework)
  3. DataContractJsonSerializer (.NET Framework 3.5)
  4. Newton Json.net ( json.codeplex.com , james.newtonking.com/pages/json-net.aspx )
  5. JsonEx ( code.google.com/p/jsonexserializer )
  6. Fluent Json ( fluentjson.codeplex.com , code.google.com/p/fluent-json )


To measure performance, two types of tests were conducted:
Test No. 1. 10,000 times the serializer was initialized and the same object was serialized.

Test number 2. 1 time the serializer was created and initialized. Serialization was performed 10,000 times. The test was invented with the hope that the “smart” serializer, having received information about the type of object in advance, will perform the conversion faster. In some cases, preliminary initialization is not possible, further the results of such tests will be marked with a dash.

Testing Environment:
Among the subjects there are two classes that are part of the platform, which means that there may be differences in their work in Mono and .NET. I have Ubuntu as the main and only OS, so for testing .NET, I used the VirtualBox virtual machine. And to be precise:
  • Mono configuration: Intel Atom 330, 4Gb + Ubuntu 10.10, MonoDevelop 2.6, Mono 2.10.5
  • .NET Configuration: VirtualBox, 1.5GB, Windows XP, VS2010, .NET Framework 3.5

String concatenation


First of all, I will give the results of testing serialization by simple ToString () and concatenation. In "production" this method can only be justified in rare cases. I consider it in order to use it as a reference. It’s hard to come up with a way to get a JSON string faster.
Test results below:
Test number 1 Test number 2
.NET 0.25 sec -
Mono 0.6 sec -

Carrying out test No. 2, for obvious reasons, is impossible.

JavaScriptSerializer


JavaScriptSerializer is located in the System.Web.Script.Serialization namespace of the .NET / Mono platforms. Code example:
var serializer = new JavaScriptSerializer();//Инициализация
string jsonResult = serializer.Serialize(Program.bookA);//Сериализация


The ability to override serialization methods for various data types using the JavaScriptConverter, RegisterConverters classes is declared. This can be useful, for example, for converting DateTime or enum s. Tests were conducted without using this feature.

Test results:
Test number 1 Test number 2
.NET 4 sec 3.5 sec
Mono 5 sec 5 sec


DataContractJsonSerializer


Another serializer available out of the box is in the System.Runtime.Serialization.Json namespace. In use, it does not differ much from the previous one, except that serialization occurs in stream, and not in a string. Example:
var serializer = new DataContractJsonSerializer(typeof(Book));
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, Program.bookA);
string jsonResult = Encoding.Default.GetString(ms.GetBuffer());


There are differences in using this tool in .NET and Mono. In .NET, you must mark serializable classes and properties with the [DataContract] and [DataMember] attributes, respectively. In Mono, these attributes are optional.
Test results show that the difference is not only in the attributes:
Test number 1 Test number 2
.NET 1.5 sec 1.5 sec
Mono 34 sec 34 sec

Looking ahead, I will say 1.5 seconds - this is the best time among all subjects, 34 seconds is the worst.

Fluent json


The advantage (and to whom and the disadvantage) of this serializer is that it provides a flexible way of mapping properties. There is no need to enter attributes into the business logic layer, which is problematic when working with third-party libraries. No intermediate classes are needed to transform the data structures of the business logic layer into data structures of the client-server exchange. Another of the claimed "chips" is the possibility of multi-threaded processing of large data sets, which gives high performance. Not my case.

The sample code below shows how this works:

var serializer = Json.EnсoderFor(config => config
                .MapType(map => map
                    .AllFields()
                    .Field(field => field.PubDate, pubDate => pubDate
                        .EncodeAs(value => value.ToShortDateString()))
                    .Field(field => field.Type, type => type
                        .EncodeAs(value => (int)value)
                        .To("book_type")))
                .MapType(map => map.AllFields())
				.UseTidy(true) );
string jsonResult = serializer.Enсode(Program.bookA);


If the serializable data type contains properties of the enumeration type or DateTime, as in the example above, then it is mandatory to specify a transformation for them. On its own, Fluent Json wonders what to do with them.

Test results:
Test number 1 Test number 2
.NET 52.5 sec 9 sec
Mono 34 sec 10 sec

JsonExSerializer


According to the assurances of the developer, this tool is designed for accurate serialization / deserialization of objects that other libraries do not provide. For me this is not the most important thing, I will test for speed. Code example:
var serializer = new Serializer(typeof(Book));
var memoryStream = new MemoryStream();
serializer.Serialize(Program.bookA,	memoryStream);
var jsonResult = Encoding.Default.GetString(memoryStream.GetBuffer());


A juicy feature of JsonEx is that it adds formatting and a comment of the form to the result:
/*
  Created by JsonExSerializer
  Assembly: JsonTestConsole, Version=1.0.4347.32516, Culture=neutral, PublicKeyToken=null
  Type: JsonTestConsole.Book
*/

Formatting can be useful when saving, for example, settings to a file, which can later be edited in a text editor.

Test results:
Test number 1 Test number 2
.NET 32 sec 8 sec
Mono 34 sec 10 sec

Newton JSON.NET


There is an intriguing line in the description of the features: “High performance, faster than .NET's built-in JSON serializers”. Sample code using Newton fits into one line:
string jsonResult = JsonConvert.SerializeObject(Program.bookA);


It does not require any initialization, but it shows a very good time:
Test number 1 Test number 2
.NET 1.5 sec -
Mono 2 sec -


Conclusion


Test results sorted by increasing time (in milliseconds) for both configurations (column K shows how many times the test is slower than “string concatenation”):

Platform Mono .Net Framework
Serializer Test number 1 Test number 2 K Test number 1 Test number 2 K
String concatination 600 - 1 250 - 1
Newton JSON.NET 2,000 - 3.4 1,500 - 6
JavaScriptSerializer 5,000 4,000 8.3 / 6.7 1700 1700 6.8
JsonExSerializer 34,000 10,000 56.7 / 16.7 4,000 3,500 16/14
Fluent json 34,000 10,000 56.7 / 16.7 32,000 8,000 128/32
DataContractJsonSerializer 34,000 34,000 56.7 / 56.7 1,500 1,500 6

The table shows that if there are plans to drive the application under Mono or the platform is not defined, then it is better to turn to the third-party library Newton JSON.net - it shows good results both in Win + .NET and Linux + Mono. If the target .NET platform and attribute binding do not bother, the built-in DataContractJsonSerializer is sufficient. If both options do not suit you, you can invent your own library - there is much to strive for.

Test code here: code.google.com/p/research-net-json/source/browse/Main.cs . Third-party libraries will have to be downloaded independently, once again the links:


UPD. I supplement the tests with several more serializers (thanks to atd , skyboy , Guderian and kekekeks ):
Platform Mono .Net Framework
Serializer Test number 1 Test number 2 K Test number 1 Test number 2 K
new StringBuilder (400) 550 - 0.9 270 - 1
Servicestack 1,300 - 2.2 1,200 - 4.8
Fast json 2 600 - 4.3 1,200 - 4.8
Jayrock 8,200 - 13.7 9,200 - 36.8

As you can see, a new leader has appeared - ServiceStack.

PS If you notice a mistake, or you know other libraries, write, I will gladly supplement the article.

Also popular now: