go-serialization-benchmarks

June 16, 2025 · View on GitHub

In this benchmarks:

  • All serializers use the same data. It is generated once and then reused by all of them.
  • Each serializer is described with a set of features.
  • A single serializer can have multiple benchmark results. For example, MUS has results labeled mus+raw and mus+unsafe. The former means the raw encoding was used during benchmarking, while the latter refers to the use of unsafe code.
  • Unmarshalled data is compared to the original data.

Results

Benchmark results are available in results/benchmarks.txt, and the corresponding benchstat output is in results/benchstat.txt.

Fastest Safe

NAMENS/OPB/SIZEB/OPALLOCS/OP
mus102.9058.0048.001
bebop200sc108.8061.0048.001
benc111.1058.0048.001
protobuf_mus163.7069.0048.001
vtprotobuf192.5069.00192.003
protobuf531.7069.00271.004
json2779.00150.00600.009
gob17050.00159.009493.50195

Fastest Unsafe

NAMENS/OPB/SIZEB/OPALLOCS/OP
mus77.2158.000.000
benc85.2958.000.000
protobuf_mus136.4069.000.000
vtprotobuf161.4069.00144.002

, where ns/op, B/op, allocs/op are standard go test -bench=. output and B/size - determines how many bytes were used on average by the serializer to encode data.

List of Features

Each feature describes a property of a serializer:

  • reflect – uses reflection.
  • codegen – uses code generation.
  • manual – only provides serialization primitives, requiring manual usage.
  • text – uses a text-based serialization format.
  • binary – uses a binary serialization format.
  • varint – supports varint encoding.
  • raw – supports raw encoding.
  • int – supports the int type.
  • native – uses native data structures.

Features that must appear in the result name when used:

  • reuse – supports buffer reuse.
  • unsafe – uses unsafe code.
  • unsafestr – uses unsafe code only for string serialization.
  • unsafeunm – uses unsafe code only for unmarshalling.
  • notunsafe – uses unsafe code for all types except string, and copies data during unmarshalling.
  • fixbuf - uses a fixed buffer.

Data

Randomly generated data has the following form:

type Data struct {
  Str     string
  Bool    bool
  Int32   int32
  Float64 float64
  Time    time.Time
}

Run Benchmarks

go test -bench=.

To filter serializers - for example, by binary and manual types:

go test -bench=. -- -f binary,manual

To run benchmarks for one particular case just name it, for example:

go test -bench=BenchmarkSerializers/mus

To see the results obtained using the reuse feature:

go test -bench=/.+reuse

Generate README.md

go generate

Recomendation

When running benchmarks on a laptop, make sure that it is connected to a charger and the fan is at full speed.

Contribution

First of all, you need to create a new package for your serializer if it doesn't already exist. Then:

  1. Implement benchser.Serializer interface.
  2. If you use own Data make shure it implements EqualTo(data Data) error method, also add func ToYourData(data serializer.Data) (d Data) function (an example can be found in projects/bbebop200sc/serializers.go).
  3. Define
    var Serializers = []benchser.Serializer[...]{...}
    
    variable. Note that it can contain several serializers that produce different results.
  4. Create PR.

If you want to run benchmarks from your own project, there is the benchser.BenchmarkSerializer(...) function.