🧊

C# バイナリ/JSONシリアライザ選択

2024/07/28に公開

要点

ベンチマーク

Method Mean Error StdDev Gen0 Gen1 Allocated
MemoryPack 91.80 ns 0.143 ns 0.120 ns 0.0229 - 144 B
MessagePack 125.93 ns 0.249 ns 0.233 ns 0.0215 - 136 B
DotnetJsonSerialize 275.47 ns 0.644 ns 0.602 ns 0.0267 - 168 B
NewtonJsonSerialize 565.93 ns 1.130 ns 1.001 ns 0.6514 0.0038 4088 B
Utf8JsonSerialize 140.31 ns 0.210 ns 0.197 ns 0.0343 - 216 B
MessagePackJsonSerialize 702.00 ns 0.772 ns 0.722 ns 0.1526 - 960 B

結論としてはJSONだけで良いのであればSystem.Text.Jsonで良さそうです。結果だけ見るとUtf8Jsonが優秀なのですがリポジトリがアーカイブ状態なので採用は厳しそうです。

MessagePackJsonSerializeはMessagePackのJSON出力機能のベンチマークです。JSONシリアライザのベンチマークを作ってた時、MessagePackにもJSON変換機能が入っていたので、一応項目に加えてみました。
MessagePackでJSONを出力するには一旦byte[]に変換しないといけないのでその手間が結果に響いています。なので「今MessagePackを使っているけど、その中の一部データをJSONにしたい」など、すでにMessagePackを採用しているのであれば良い選択だと思いますが、逆にJSONだけしか使う予定がないのであれば、わざわざMessagePackのJSON変換を使う必要は無さそうです。

ていうか

Utf8Json凄いですね・・・復活願ってます。

ベンチマークコード

[MemoryPackable]
[MessagePackObject]
public partial class Person
{
    [Key(nameof(Age))]
    public int Age { get; set; }

    [Key(nameof(Name))]
    public string Name { get; set; }
}

[MemoryDiagnoser]
public class BinarySerializerBench
{
    [Benchmark]
    public Person MemoryPack()
    {
        var v = new Person { Age = 40, Name = "John" };

        var bin = MemoryPackSerializer.Serialize(v);
        var val = MemoryPackSerializer.Deserialize<Person>(bin);

        return val;
    }

    [Benchmark]
    public Person MessagePack()
    {
        var v = new Person { Age = 40, Name = "John" };
        var bin = MessagePackSerializer.Serialize(v);
        var val = MessagePackSerializer.Deserialize<Person>(bin);

        return val;
    }

    [Benchmark]
    public Person DotnetJsonSerialize()
    {
        var v = new Person { Age = 40, Name = "John" };
        var bin = System.Text.Json.JsonSerializer.Serialize(v);
        var val = System.Text.Json.JsonSerializer.Deserialize<Person>(bin);

        return val;
    }

    [Benchmark]
    public Person NewtonJsonSerialize()
    {
        var v = new Person { Age = 40, Name = "John" };
        var bin = JsonConvert.SerializeObject(v);
        var val = JsonConvert.DeserializeObject<Person>(bin);

        return val;
    }

    [Benchmark]
    public Person Utf8JsonSerialize()
    {
        var v = new Person { Age = 40, Name = "John" };
        var bin = Utf8Json.JsonSerializer.ToJsonString(v);
        var val = Utf8Json.JsonSerializer.Deserialize<Person>(bin);

        return val;
    }

    [Benchmark]
    public Person MessagePackJsonSerialize()
    {
        var v = new Person { Age = 40, Name = "John" };
        var bin = MessagePackSerializer.Serialize(v);
        var json = MessagePackSerializer.ConvertToJson(bin);
        var res = MessagePackSerializer.ConvertFromJson(json);
        var val = MessagePackSerializer.Deserialize<Person>(res);

        return val;
    }
}

リンク

https://github.com/Cysharp/MemoryPack
https://github.com/MessagePack-CSharp/MessagePack-CSharp
https://github.com/neuecc/Utf8Json
https://www.newtonsoft.com/json

Discussion