From 53b05a5d5304db126a0b1d22dae483a5ed958f4c Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 8 Apr 2019 07:56:05 -0700 Subject: [PATCH] proto: add simple benchmark Run the encode/decode tests as benchmarks. These are trivial microbenchmarks and not representative of real-world usage, but serve as a useful overview of the relative cost of various operations and are handy for profiling specific narrow scenarios. When run with the -v1 flag, benchmark the v1 implementation for comparison. Change-Id: I469dd6759bef50e2bd039327095f82d29d70b8fc Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/171120 Reviewed-by: Joe Tsai --- proto/bench_test.go | 75 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 proto/bench_test.go diff --git a/proto/bench_test.go b/proto/bench_test.go new file mode 100644 index 00000000..a38d11ba --- /dev/null +++ b/proto/bench_test.go @@ -0,0 +1,75 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package proto_test + +import ( + "flag" + "fmt" + "reflect" + "testing" + + protoV1 "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/v2/proto" +) + +// The results of these microbenchmarks are unlikely to correspond well +// to real world peformance. They are mainly useful as a quick check to +// detect unexpected regressions and for profiling specific cases. + +var ( + benchV1 = flag.Bool("v1", false, "benchmark the v1 implementation") + allowPartial = flag.Bool("allow_partial", false, "set AllowPartial") +) + +// BenchmarkEncode benchmarks encoding all the test messages. +func BenchmarkEncode(b *testing.B) { + for _, test := range testProtos { + for _, want := range test.decodeTo { + v1 := want.(protoV1.Message) + opts := proto.MarshalOptions{AllowPartial: *allowPartial} + b.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + var err error + if *benchV1 { + _, err = protoV1.Marshal(v1) + } else { + _, err = opts.Marshal(want) + } + if err != nil { + b.Fatal(err) + } + } + }) + }) + } + } +} + +// BenchmarkDecode benchmarks decoding all the test messages. +func BenchmarkDecode(b *testing.B) { + for _, test := range testProtos { + for _, want := range test.decodeTo { + opts := proto.UnmarshalOptions{AllowPartial: *allowPartial} + b.Run(fmt.Sprintf("%s (%T)", test.desc, want), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + m := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message) + v1 := m.(protoV1.Message) + for pb.Next() { + var err error + if *benchV1 { + err = protoV1.Unmarshal(test.wire, v1) + } else { + err = opts.Unmarshal(test.wire, m) + } + if err != nil { + b.Fatal(err) + } + } + }) + }) + } + } +}