13

I have a problem - Json.Net serializing my objects realy slow. I have some basic class:

public class authenticationRequest
{
    public string userid;
    public string tid;
    public string token;
    public string platform;
    public string version;
}

And I'm serializing it with

string jsonDataToSend = JsonConvert.SerializeObject(dataToSend); 

This operation takes about 1900 ms. In compare to info from Json.net CodePlex page:

enter image description here

It takes a really long time. For test purposes I swapped my class for a simple string:

string jsonDataToSend = JsonConvert.SerializeObject("fsdfsdfsdfs");

And it still takes ~900 ms to convert. What is the reason? What I can do to serialize this data faster?

Robaticus
  • 22,857
  • 5
  • 54
  • 63
Thaven
  • 1,857
  • 3
  • 19
  • 35
  • 1
    do you have a debugger attached? is this consistently happening? – Daniel A. White Apr 10 '12 at 13:11
  • 1
    have you run multiple iterations? – Daniel A. White Apr 10 '12 at 13:12
  • In addition to @DanielA.White's concerns, how does the ~900ms compare to `DataContractJsonSerializer` and `JavaScriptSerializer` (e.g., have you recreated the entire benchmark, or just `Json.NET`)? – Donut Apr 10 '12 at 13:14
  • @DanielA.White - yes, I have debugger attached, but without it time is almost the same. And yes, this is consistently happening. No, only one iteration. – Thaven Apr 10 '12 at 13:14
  • 1
    If you run the serialization twice, does the second one take as long? – Robaticus Apr 10 '12 at 13:16
  • @Donut - I tried just Json.net, I not compared it to other libraries – Thaven Apr 10 '12 at 13:18
  • 2
    Try running it twice in a row, and see what the time is for the second one. It may be something in the constructor or loading the library that's taking the extra time. (never mind on the constructor. I just looked at the source, and there isn't one). – Robaticus Apr 10 '12 at 13:20
  • @Robaticus - no, second serialization takes only 2 ms – Thaven Apr 10 '12 at 13:22
  • the first time might be slow as its doing reflection and caching stuff. – Daniel A. White Apr 10 '12 at 13:41
  • @Thaven - also read the source for that demo. it should show you many iterations not just one. – Daniel A. White Apr 10 '12 at 13:42
  • FWIW, I've been looking into the same problem for some days now. I have a large JSON string that deserializes in about 70 seconds. But when I don't run it in debug mode... .5 seconds. – Peter Sep 03 '14 at 11:31
  • I ran into this issue as well. When running without the debugger, its lightning fast but with it attached it goes to a halt. – Oak Jun 01 '15 at 18:45

3 Answers3

18

I had the same problem with a project I'm working on and I solved it by following the advice on this page: http://www.newtonsoft.com/json/help/html/Performance.htm

Specifically, they recommend manually serializing your objects when performance is critical:

public static string ToJson(this Person p)
{
    StringWriter sw = new StringWriter();
    JsonTextWriter writer = new JsonTextWriter(sw);

    // {
    writer.WriteStartObject();

    // "name" : "Jerry"
    writer.WritePropertyName("name");
    writer.WriteValue(p.Name);

    // "likes": ["Comedy", "Superman"]
    writer.WritePropertyName("likes");
    writer.WriteStartArray();
    foreach (string like in p.Likes)
    {
        writer.WriteValue(like);
    }
    writer.WriteEndArray();

    // }
    writer.WriteEndObject();

    return sw.ToString();
}

My example in VB looks like this:

    Public Function SerializeWords(ByRef oWords As List(Of Word))
        Dim sb As New StringBuilder
        Dim sw As New IO.StringWriter(sb)
        Using oWriter As Newtonsoft.Json.JsonWriter = New Newtonsoft.Json.JsonTextWriter(sw)
            With oWriter
                .WriteStartArray()
                For Each oWord As Word In oWords
                    .WriteStartObject()

                    .WritePropertyName("ID")
                    .WriteValue(oWord.ID)

                    .WritePropertyName("Phonics")
                    .WriteValue(oWord.Phonics)

                    .WritePropertyName("Word_")
                    .WriteValue(oWord.Word_)

                    .WritePropertyName("WordLength")
                    .WriteValue(oWord.WordLength)

                    .WriteEndObject()
                Next
                .WriteEndArray()

            End With
        End Using
        Return sb.ToString

    End Function

Notice how it's strongly typed. I believe when you use Newtonsoft.Json.JsonConvert.SerializeObject() it's using reflection to get the job done (which can really add up when you have many objects with many properties).

Anyways... once I wrote my own serializer, my time serializing a list of 250 words went from 28 seconds using JsonConvert.SerializeObject() method to 31 milliseconds using my own function.

Frog Pr1nce
  • 730
  • 9
  • 8
5

What I believe is happening here is that you are getting a delay when the Json.Net library is being loaded. You should try compiling in Release mode to see if things speed up considerably, as this should prevent symbols from being loaded (which can add to the library load time).

If it is still an issue, find a good time in your app that you can do a dummy serialization (perhaps even on a background thread) to force the library to load. That has a bit of code-smell to it, though, so there may be a better way of forcing the load, but that's a brute force method that should work all the time.

Robaticus
  • 22,857
  • 5
  • 54
  • 63
1

JSON string deserialization using the "Newtonsoft.Json" library works much faster for me on ARM when deserializing to the dynamic data type instead of a custom one.

var receivedObject = JsonConvert.DeserializeObject<dynamic>(content);

but this is even faster:

dynamic receivedObject = JObject.Parse(content);
tedi
  • 6,350
  • 5
  • 52
  • 67