neuecc / Utf8Json

Definitely Fastest and Zero Allocation JSON Serializer for C#(NET, .NET Core, Unity, Xamarin).
MIT License
2.36k stars 267 forks source link

Utf8Json is nearly two times slower than Json.NET when serializing byte arrays #177

Open Alois-xx opened 4 years ago

Alois-xx commented 4 years ago

This did come somewhat unexpected:

Did serialize with Json.NET in 2.606s
Did serialize with UTF8Json in 3.998s

Code to Test:

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace MemoryAllocatedCore
{
    public class BinaryDataWrapper
    {
        public byte[] Data { get; set; }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            BinaryDataWrapper wrapper = new BinaryDataWrapper();
            wrapper.Data = Enumerable.Range(1, 512 * 1024).Select(x => (byte)x).ToArray();

            const int N = 1000;
            var sw =Stopwatch.StartNew();
            for (int i = 0; i < N; i++)
            {
                byte[] newtonSoftBytes = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(wrapper, Newtonsoft.Json.Formatting.Indented));

            }
            sw.Stop();
            GC.Collect();
            Console.WriteLine($"Did serialize with Json.NET in {sw.Elapsed.TotalSeconds:F3}s");
            sw = Stopwatch.StartNew();
            for (int i = 0; i < N; i++)
            {
                byte[] bytes = Utf8Json.JsonSerializer.Serialize(wrapper);
            }
            sw.Stop();
            Console.WriteLine($"Did serialize with UTF8Json in {sw.Elapsed.TotalSeconds:F3}s");
        }
    }
}

The main issue is that Json.NET does not try to escape characters in its JsonWriter. But Utf8Json will call in its Json Writer Utf8Json.JsonWriter.WriteString(string value) for an already Base64 encoded string. Json.NET on the other hand does no checking and directly writes the contents to the output. Is this a known issue and would it easy to solve?

ahsonkhan commented 4 years ago

For completeness/comparison, added S.T.Json (for the particular case of writing Base64 encoded strings):

sw = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
{
    byte[] bytes = System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(wrapper);
}
sw.Stop();
GC.Collect();
Console.WriteLine($"Did serialize with S.T.Json in {sw.Elapsed.TotalSeconds:F3}s");
dotnet run -c Release
Did serialize with Json.NET in 1.907s
Did serialize with UTF8Json in 2.846s
Did serialize with S.T.Json in 0.248s