diff options
Diffstat (limited to 'internal/benchmarks/micro/micro_test.go')
-rw-r--r-- | internal/benchmarks/micro/micro_test.go | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/internal/benchmarks/micro/micro_test.go b/internal/benchmarks/micro/micro_test.go new file mode 100644 index 00000000..dd967448 --- /dev/null +++ b/internal/benchmarks/micro/micro_test.go @@ -0,0 +1,198 @@ +// Copyright 2020 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. + +// This package contains microbenchmarks exercising specific areas of interest. +// The benchmarks here are not comprehensive and are not necessarily indicative +// real-world performance. + +package micro_test + +import ( + "testing" + + "google.golang.org/protobuf/internal/impl" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/runtime/protoiface" + "google.golang.org/protobuf/types/known/emptypb" + + micropb "google.golang.org/protobuf/internal/testprotos/benchmarks/micro" + testpb "google.golang.org/protobuf/internal/testprotos/test" +) + +// BenchmarkEmptyMessage tests a google.protobuf.Empty. +// +// It measures per-operation overhead. +func BenchmarkEmptyMessage(b *testing.B) { + b.Run("Wire/Marshal", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + m := &emptypb.Empty{} + for pb.Next() { + if _, err := proto.Marshal(m); err != nil { + b.Fatal(err) + } + } + }) + }) + b.Run("Wire/Unmarshal", func(b *testing.B) { + opts := proto.UnmarshalOptions{ + Merge: true, + } + b.RunParallel(func(pb *testing.PB) { + m := &emptypb.Empty{} + for pb.Next() { + if err := opts.Unmarshal([]byte{}, m); err != nil { + b.Fatal(err) + } + } + }) + }) + b.Run("Wire/Validate", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + mt := (&emptypb.Empty{}).ProtoReflect().Type() + for pb.Next() { + _, got := impl.Validate(mt, protoiface.UnmarshalInput{}) + want := impl.ValidationValid + if got != want { + b.Fatalf("Validate = %v, want %v", got, want) + } + } + }) + }) + b.Run("Clone", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + m := &emptypb.Empty{} + for pb.Next() { + proto.Clone(m) + } + }) + }) +} + +// BenchmarkRepeatedInt32 tests a message containing 500 non-packed repeated int32s. +// +// For unmarshal operations, it measures the cost of the field decode loop, since each +// item in the repeated field has an individual tag and value. +func BenchmarkRepeatedInt32(b *testing.B) { + m := &testpb.TestAllTypes{} + for i := int32(0); i < 500; i++ { + m.RepeatedInt32 = append(m.RepeatedInt32, i) + } + w, err := proto.Marshal(m) + if err != nil { + b.Fatal(err) + } + b.Run("Wire/Marshal", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + if _, err := proto.Marshal(m); err != nil { + b.Fatal(err) + } + } + }) + }) + b.Run("Wire/Unmarshal", func(b *testing.B) { + opts := proto.UnmarshalOptions{ + Merge: true, + } + b.RunParallel(func(pb *testing.PB) { + m := &testpb.TestAllTypes{} + for pb.Next() { + m.RepeatedInt32 = m.RepeatedInt32[:0] + if err := opts.Unmarshal(w, m); err != nil { + b.Fatal(err) + } + } + }) + }) + b.Run("Wire/Validate", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + mt := (&testpb.TestAllTypes{}).ProtoReflect().Type() + for pb.Next() { + _, got := impl.Validate(mt, protoiface.UnmarshalInput{ + Buf: w, + }) + want := impl.ValidationValid + if got != want { + b.Fatalf("Validate = %v, want %v", got, want) + } + } + }) + }) + b.Run("Clone", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + proto.Clone(m) + } + }) + }) +} + +// BenchmarkRequired tests a message containing a required field. +func BenchmarkRequired(b *testing.B) { + m := µpb.SixteenRequired{ + F1: proto.Int32(1), + F2: proto.Int32(1), + F3: proto.Int32(1), + F4: proto.Int32(1), + F5: proto.Int32(1), + F6: proto.Int32(1), + F7: proto.Int32(1), + F8: proto.Int32(1), + F9: proto.Int32(1), + F10: proto.Int32(1), + F11: proto.Int32(1), + F12: proto.Int32(1), + F13: proto.Int32(1), + F14: proto.Int32(1), + F15: proto.Int32(1), + F16: proto.Int32(1), + } + w, err := proto.Marshal(m) + if err != nil { + b.Fatal(err) + } + b.Run("Wire/Marshal", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + if _, err := proto.Marshal(m); err != nil { + b.Fatal(err) + } + } + }) + }) + b.Run("Wire/Unmarshal", func(b *testing.B) { + opts := proto.UnmarshalOptions{ + Merge: true, + } + b.RunParallel(func(pb *testing.PB) { + m := µpb.SixteenRequired{} + for pb.Next() { + if err := opts.Unmarshal(w, m); err != nil { + b.Fatal(err) + } + } + }) + }) + b.Run("Wire/Validate", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + mt := (µpb.SixteenRequired{}).ProtoReflect().Type() + for pb.Next() { + _, got := impl.Validate(mt, protoiface.UnmarshalInput{ + Buf: w, + }) + want := impl.ValidationValid + if got != want { + b.Fatalf("Validate = %v, want %v", got, want) + } + } + }) + }) + b.Run("Clone", func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + proto.Clone(m) + } + }) + }) +} |