/go_serialization_benchmarks

Benchmarks of Go serialization methods

Primary LanguageGo

Benchmarks of Go serialization methods

Gitter chat

This is a test suite for benchmarking various Go serialization methods.

Tested serialization methods

Running the benchmarks

go get -u -t
go test -bench='.*' ./

To update the table in the README:

./stats.sh

Recommendation

If performance, correctness and interoperability are the most important factors, gogoprotobuf is currently the best choice. It does require a pre-processing step (eg. via Go 1.4's "go generate" command).

But as always, make your own choice based on your requirements.

Data

The data being serialized is the following structure with randomly generated values:

type A struct {
    Name     string
    BirthDay time.Time
    Phone    string
    Siblings int
    Spouse   bool
    Money    float64
}

Results

2019-08-28 Results with Go 1.12.6 darwin/amd64 on a 2.8 GHz Intel Core i7 16GB

benchmark iter time/iter bytes/op allocs/op tt.sec tt.kb ns/alloc
BenchmarkGotinyMarshal-8 20000000 99 ns/op 0 0 1.99 0 0.00
BenchmarkGotinyUnmarshal-8 10000000 192 ns/op 112 3 1.92 112000 64.00
BenchmarkGotinyNoTimeMarshal-8 20000000 99 ns/op 0 0 1.98 0 0.00
BenchmarkGotinyNoTimeUnmarshal-8 10000000 175 ns/op 96 3 1.75 96000 58.33
BenchmarkMsgpMarshal-8 10000000 140 ns/op 128 1 1.40 128000 140.00
BenchmarkMsgpUnmarshal-8 5000000 280 ns/op 112 3 1.40 56000 93.33
BenchmarkVmihailencoMsgpackMarshal-8 2000000 986 ns/op 400 7 1.97 80000 140.86
BenchmarkVmihailencoMsgpackUnmarshal-8 1000000 1271 ns/op 416 13 1.27 41600 97.77
BenchmarkJsonMarshal-8 1000000 1585 ns/op 304 4 1.58 30400 396.25
BenchmarkJsonUnmarshal-8 500000 3307 ns/op 359 7 1.65 17950 472.43
BenchmarkJsonIterMarshal-8 1000000 1768 ns/op 312 5 1.77 31200 353.60
BenchmarkJsonIterUnmarshal-8 1000000 1361 ns/op 263 6 1.36 26300 226.83
BenchmarkEasyJsonMarshal-8 1000000 1125 ns/op 784 5 1.12 78400 225.00
BenchmarkEasyJsonUnmarshal-8 1000000 1208 ns/op 159 4 1.21 15900 302.00
BenchmarkBsonMarshal-8 1000000 1005 ns/op 392 10 1.00 39200 100.50
BenchmarkBsonUnmarshal-8 1000000 1559 ns/op 244 19 1.56 24400 82.05
BenchmarkGobMarshal-8 2000000 744 ns/op 48 2 1.49 9600 372.00
BenchmarkGobUnmarshal-8 2000000 793 ns/op 112 3 1.59 22400 264.33
BenchmarkXdrMarshal-8 1000000 1332 ns/op 392 19 1.33 39200 70.11
BenchmarkXdrUnmarshal-8 1000000 1200 ns/op 224 11 1.20 22400 109.09
BenchmarkUgorjiCodecMsgpackMarshal-8 2000000 922 ns/op 1312 3 1.84 262400 307.33
BenchmarkUgorjiCodecMsgpackUnmarshal-8 1000000 1036 ns/op 496 4 1.04 49600 259.00
BenchmarkUgorjiCodecBincMarshal-8 1000000 1019 ns/op 1328 4 1.02 132800 254.75
BenchmarkUgorjiCodecBincUnmarshal-8 1000000 1179 ns/op 640 7 1.18 64000 168.43
BenchmarkSerealMarshal-8 1000000 2192 ns/op 904 20 2.19 90400 109.60
BenchmarkSerealUnmarshal-8 500000 2634 ns/op 1008 34 1.32 50400 77.47
BenchmarkBinaryMarshal-8 1000000 1207 ns/op 326 21 1.21 32600 57.48
BenchmarkBinaryUnmarshal-8 1000000 1218 ns/op 320 22 1.22 32000 55.36
BenchmarkFlatBuffersMarshal-8 5000000 266 ns/op 0 0 1.33 0 0.00
BenchmarkFlatBuffersUnmarshal-8 10000000 212 ns/op 112 3 2.12 112000 70.67
BenchmarkCapNProtoMarshal-8 5000000 369 ns/op 56 2 1.84 28000 184.50
BenchmarkCapNProtoUnmarshal-8 5000000 355 ns/op 200 6 1.77 100000 59.17
BenchmarkCapNProto2Marshal-8 3000000 571 ns/op 244 3 1.71 73200 190.33
BenchmarkCapNProto2Unmarshal-8 2000000 792 ns/op 320 6 1.58 64000 132.00
BenchmarkHproseMarshal-8 2000000 772 ns/op 331 8 1.54 66200 96.50
BenchmarkHproseUnmarshal-8 2000000 959 ns/op 319 10 1.92 63800 95.90
BenchmarkHprose2Marshal-8 3000000 475 ns/op 0 0 1.43 0 0.00
BenchmarkHprose2Unmarshal-8 3000000 491 ns/op 144 4 1.47 43200 122.75
BenchmarkProtobufMarshal-8 2000000 738 ns/op 152 7 1.48 30400 105.43
BenchmarkProtobufUnmarshal-8 2000000 686 ns/op 192 10 1.37 38400 68.60
BenchmarkGoprotobufMarshal-8 5000000 337 ns/op 96 2 1.69 48000 168.50
BenchmarkGoprotobufUnmarshal-8 3000000 533 ns/op 200 10 1.60 60000 53.30
BenchmarkGogoprotobufMarshal-8 10000000 132 ns/op 64 1 1.32 64000 132.00
BenchmarkGogoprotobufUnmarshal-8 10000000 187 ns/op 96 3 1.87 96000 62.33
BenchmarkColferMarshal-8 20000000 108 ns/op 64 1 2.16 128000 108.00
BenchmarkColferUnmarshal-8 10000000 156 ns/op 112 3 1.56 112000 52.00
BenchmarkGencodeMarshal-8 10000000 134 ns/op 80 2 1.34 80000 67.00
BenchmarkGencodeUnmarshal-8 10000000 160 ns/op 112 3 1.60 112000 53.33
BenchmarkGencodeUnsafeMarshal-8 20000000 85 ns/op 48 1 1.70 96000 85.00
BenchmarkGencodeUnsafeUnmarshal-8 10000000 123 ns/op 96 3 1.23 96000 41.00
BenchmarkXDR2Marshal-8 10000000 140 ns/op 64 1 1.40 64000 140.00
BenchmarkXDR2Unmarshal-8 20000000 111 ns/op 32 2 2.22 64000 55.50
BenchmarkGoAvroMarshal-8 1000000 2331 ns/op 1030 32 2.33 103000 72.84
BenchmarkGoAvroUnmarshal-8 300000 5496 ns/op 3372 87 1.65 101160 63.17
BenchmarkGoAvro2TextMarshal-8 1000000 2225 ns/op 1326 20 2.23 132600 111.25
BenchmarkGoAvro2TextUnmarshal-8 1000000 2338 ns/op 806 33 2.34 80600 70.85
BenchmarkGoAvro2BinaryMarshal-8 2000000 791 ns/op 510 11 1.58 102000 71.91
BenchmarkGoAvro2BinaryUnmarshal-8 2000000 829 ns/op 576 13 1.66 115200 63.77
BenchmarkIkeaMarshal-8 3000000 537 ns/op 72 8 1.61 21600 67.12
BenchmarkIkeaUnmarshal-8 2000000 681 ns/op 160 11 1.36 32000 61.91
BenchmarkShamatonMapMsgpackMarshal-8 2000000 680 ns/op 208 4 1.36 41600 170.00
BenchmarkShamatonMapMsgpackUnmarshal-8 2000000 611 ns/op 144 3 1.22 28800 203.67
BenchmarkShamatonArrayMsgpackMarshal-8 2000000 604 ns/op 176 4 1.21 35200 151.00
BenchmarkShamatonArrayMsgpackUnmarshal-8 3000000 409 ns/op 144 3 1.23 43200 136.33
BenchmarkSSZNoTimeNoStringNoFloatAMarshal-8 300000 4003 ns/op 440 71 1.20 13200 56.38
BenchmarkSSZNoTimeNoStringNoFloatAUnmarshal-8 200000 6519 ns/op 1392 78 1.30 27840 83.58

Totals:

benchmark iter time/iter bytes/op allocs/op tt.sec tt.kb ns/alloc
BenchmarkGencodeUnsafe-8 30000000 208 ns/op 144 4 6.24 432000 52.00
BenchmarkXDR2-8 30000000 251 ns/op 96 3 7.53 288000 83.67
BenchmarkColfer-8 30000000 264 ns/op 176 4 7.92 528000 66.00
BenchmarkGotinyNoTime-8 30000000 274 ns/op 96 3 8.22 288000 91.37
BenchmarkGotiny-8 30000000 291 ns/op 112 3 8.74 336000 97.10
BenchmarkGencode-8 20000000 294 ns/op 192 5 5.88 384000 58.80
BenchmarkGogoprotobuf-8 20000000 319 ns/op 160 4 6.38 320000 79.75
BenchmarkMsgp-8 15000000 420 ns/op 240 4 6.30 360000 105.00
BenchmarkFlatBuffers-8 15000000 478 ns/op 112 3 7.17 168000 159.33
BenchmarkCapNProto-8 10000000 724 ns/op 256 8 7.24 256000 90.50
BenchmarkGoprotobuf-8 8000000 870 ns/op 296 12 6.96 236800 72.50
BenchmarkHprose2-8 6000000 966 ns/op 144 4 5.80 86400 241.50
BenchmarkShamatonArrayMsgpack-8 5000000 1013 ns/op 320 7 5.07 160000 144.71
BenchmarkIkea-8 5000000 1218 ns/op 232 19 6.09 116000 64.11
BenchmarkShamatonMapMsgpack-8 4000000 1291 ns/op 352 7 5.16 140800 184.43
BenchmarkCapNProto2-8 5000000 1363 ns/op 564 9 6.82 282000 151.44
BenchmarkProtobuf-8 4000000 1424 ns/op 344 17 5.70 137600 83.76
BenchmarkGob-8 4000000 1537 ns/op 160 5 6.15 64000 307.40
BenchmarkGoAvro2Binary-8 4000000 1620 ns/op 1086 24 6.48 434400 67.50
BenchmarkHprose-8 4000000 1731 ns/op 650 18 6.92 260000 96.17
BenchmarkUgorjiCodecMsgpack-8 3000000 1958 ns/op 1808 7 5.87 542400 279.71
BenchmarkUgorjiCodecBinc-8 2000000 2198 ns/op 1968 11 4.40 393600 199.82
BenchmarkVmihailencoMsgpack-8 3000000 2257 ns/op 816 20 6.77 244800 112.85
BenchmarkEasyJson-8 2000000 2333 ns/op 943 9 4.67 188600 259.22
BenchmarkBinary-8 2000000 2425 ns/op 646 43 4.85 129200 56.40
BenchmarkXdr-8 2000000 2532 ns/op 616 30 5.06 123200 84.40
BenchmarkBson-8 2000000 2564 ns/op 636 29 5.13 127200 88.41
BenchmarkJsonIter-8 2000000 3129 ns/op 575 11 6.26 115000 284.45
BenchmarkGoAvro2Text-8 2000000 4563 ns/op 2132 53 9.13 426400 86.09
BenchmarkSereal-8 1500000 4826 ns/op 1912 54 7.24 286800 89.37
BenchmarkJson-8 1500000 4892 ns/op 663 11 7.34 99450 444.73
BenchmarkGoAvro-8 1300000 7827 ns/op 4402 119 10.18 572260 65.77
BenchmarkSSZNoTimeNoStringNoFloatA-8 500000 10522 ns/op 1832 149 5.26 91600 70.62

Issues

The benchmarks can also be run with validation enabled.

VALIDATE=1 go test -bench='.*' ./

Unfortunately, several of the serializers exhibit issues:

  1. (minor) BSON drops sub-microsecond precision from time.Time.
  2. (minor) Ugorji Binc Codec drops the timezone name (eg. "EST" -> "-0500") from time.Time.
--- FAIL: BenchmarkBsonUnmarshal-8
    serialization_benchmarks_test.go:115: unmarshaled object differed:
        &{20b999e3621bd773 2016-01-19 14:05:02.469416459 -0800 PST f017c8e9de 4 true 0.20887343719329818}
        &{20b999e3621bd773 2016-01-19 14:05:02.469 -0800 PST f017c8e9de 4 true 0.20887343719329818}
--- FAIL: BenchmarkUgorjiCodecBincUnmarshal-8
    serialization_benchmarks_test.go:115: unmarshaled object differed:
        &{20a1757ced6b488e 2016-01-19 14:05:15.69474534 -0800 PST 71f3bf4233 0 false 0.8712180830484527}
        &{20a1757ced6b488e 2016-01-19 14:05:15.69474534 -0800 -0800 71f3bf4233 0 false 0.8712180830484527}

All other fields are correct however.

Additionally, while not a correctness issue, FlatBuffers, ProtoBuffers, Cap'N'Proto and ikeapack do not support time types directly. In the benchmarks an int64 value is used to hold a UnixNano timestamp.