blob: dd967448bb68783bb7586802387df594ede4c24f [file] [log] [blame]
// 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 := &micropb.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 := &micropb.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 := (&micropb.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)
}
})
})
}