1*1c12ee1eSDan Willemsen// Copyright 2020 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsen// This package contains microbenchmarks exercising specific areas of interest. 6*1c12ee1eSDan Willemsen// The benchmarks here are not comprehensive and are not necessarily indicative 7*1c12ee1eSDan Willemsen// real-world performance. 8*1c12ee1eSDan Willemsen 9*1c12ee1eSDan Willemsenpackage micro_test 10*1c12ee1eSDan Willemsen 11*1c12ee1eSDan Willemsenimport ( 12*1c12ee1eSDan Willemsen "testing" 13*1c12ee1eSDan Willemsen 14*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/impl" 15*1c12ee1eSDan Willemsen "google.golang.org/protobuf/proto" 16*1c12ee1eSDan Willemsen "google.golang.org/protobuf/runtime/protoiface" 17*1c12ee1eSDan Willemsen "google.golang.org/protobuf/types/known/emptypb" 18*1c12ee1eSDan Willemsen 19*1c12ee1eSDan Willemsen micropb "google.golang.org/protobuf/internal/testprotos/benchmarks/micro" 20*1c12ee1eSDan Willemsen testpb "google.golang.org/protobuf/internal/testprotos/test" 21*1c12ee1eSDan Willemsen) 22*1c12ee1eSDan Willemsen 23*1c12ee1eSDan Willemsen// BenchmarkEmptyMessage tests a google.protobuf.Empty. 24*1c12ee1eSDan Willemsen// 25*1c12ee1eSDan Willemsen// It measures per-operation overhead. 26*1c12ee1eSDan Willemsenfunc BenchmarkEmptyMessage(b *testing.B) { 27*1c12ee1eSDan Willemsen b.Run("Wire/Marshal", func(b *testing.B) { 28*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 29*1c12ee1eSDan Willemsen m := &emptypb.Empty{} 30*1c12ee1eSDan Willemsen for pb.Next() { 31*1c12ee1eSDan Willemsen if _, err := proto.Marshal(m); err != nil { 32*1c12ee1eSDan Willemsen b.Fatal(err) 33*1c12ee1eSDan Willemsen } 34*1c12ee1eSDan Willemsen } 35*1c12ee1eSDan Willemsen }) 36*1c12ee1eSDan Willemsen }) 37*1c12ee1eSDan Willemsen b.Run("Wire/Unmarshal", func(b *testing.B) { 38*1c12ee1eSDan Willemsen opts := proto.UnmarshalOptions{ 39*1c12ee1eSDan Willemsen Merge: true, 40*1c12ee1eSDan Willemsen } 41*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 42*1c12ee1eSDan Willemsen m := &emptypb.Empty{} 43*1c12ee1eSDan Willemsen for pb.Next() { 44*1c12ee1eSDan Willemsen if err := opts.Unmarshal([]byte{}, m); err != nil { 45*1c12ee1eSDan Willemsen b.Fatal(err) 46*1c12ee1eSDan Willemsen } 47*1c12ee1eSDan Willemsen } 48*1c12ee1eSDan Willemsen }) 49*1c12ee1eSDan Willemsen }) 50*1c12ee1eSDan Willemsen b.Run("Wire/Validate", func(b *testing.B) { 51*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 52*1c12ee1eSDan Willemsen mt := (&emptypb.Empty{}).ProtoReflect().Type() 53*1c12ee1eSDan Willemsen for pb.Next() { 54*1c12ee1eSDan Willemsen _, got := impl.Validate(mt, protoiface.UnmarshalInput{}) 55*1c12ee1eSDan Willemsen want := impl.ValidationValid 56*1c12ee1eSDan Willemsen if got != want { 57*1c12ee1eSDan Willemsen b.Fatalf("Validate = %v, want %v", got, want) 58*1c12ee1eSDan Willemsen } 59*1c12ee1eSDan Willemsen } 60*1c12ee1eSDan Willemsen }) 61*1c12ee1eSDan Willemsen }) 62*1c12ee1eSDan Willemsen b.Run("Clone", func(b *testing.B) { 63*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 64*1c12ee1eSDan Willemsen m := &emptypb.Empty{} 65*1c12ee1eSDan Willemsen for pb.Next() { 66*1c12ee1eSDan Willemsen proto.Clone(m) 67*1c12ee1eSDan Willemsen } 68*1c12ee1eSDan Willemsen }) 69*1c12ee1eSDan Willemsen }) 70*1c12ee1eSDan Willemsen b.Run("New", func(b *testing.B) { 71*1c12ee1eSDan Willemsen mt := (&emptypb.Empty{}).ProtoReflect().Type() 72*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 73*1c12ee1eSDan Willemsen for pb.Next() { 74*1c12ee1eSDan Willemsen mt.New() 75*1c12ee1eSDan Willemsen } 76*1c12ee1eSDan Willemsen }) 77*1c12ee1eSDan Willemsen }) 78*1c12ee1eSDan Willemsen} 79*1c12ee1eSDan Willemsen 80*1c12ee1eSDan Willemsen// BenchmarkRepeatedInt32 tests a message containing 500 non-packed repeated int32s. 81*1c12ee1eSDan Willemsen// 82*1c12ee1eSDan Willemsen// For unmarshal operations, it measures the cost of the field decode loop, since each 83*1c12ee1eSDan Willemsen// item in the repeated field has an individual tag and value. 84*1c12ee1eSDan Willemsenfunc BenchmarkRepeatedInt32(b *testing.B) { 85*1c12ee1eSDan Willemsen m := &testpb.TestAllTypes{} 86*1c12ee1eSDan Willemsen for i := int32(0); i < 500; i++ { 87*1c12ee1eSDan Willemsen m.RepeatedInt32 = append(m.RepeatedInt32, i) 88*1c12ee1eSDan Willemsen } 89*1c12ee1eSDan Willemsen w, err := proto.Marshal(m) 90*1c12ee1eSDan Willemsen if err != nil { 91*1c12ee1eSDan Willemsen b.Fatal(err) 92*1c12ee1eSDan Willemsen } 93*1c12ee1eSDan Willemsen b.Run("Wire/Marshal", func(b *testing.B) { 94*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 95*1c12ee1eSDan Willemsen for pb.Next() { 96*1c12ee1eSDan Willemsen if _, err := proto.Marshal(m); err != nil { 97*1c12ee1eSDan Willemsen b.Fatal(err) 98*1c12ee1eSDan Willemsen } 99*1c12ee1eSDan Willemsen } 100*1c12ee1eSDan Willemsen }) 101*1c12ee1eSDan Willemsen }) 102*1c12ee1eSDan Willemsen b.Run("Wire/Unmarshal", func(b *testing.B) { 103*1c12ee1eSDan Willemsen opts := proto.UnmarshalOptions{ 104*1c12ee1eSDan Willemsen Merge: true, 105*1c12ee1eSDan Willemsen } 106*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 107*1c12ee1eSDan Willemsen m := &testpb.TestAllTypes{} 108*1c12ee1eSDan Willemsen for pb.Next() { 109*1c12ee1eSDan Willemsen m.RepeatedInt32 = m.RepeatedInt32[:0] 110*1c12ee1eSDan Willemsen if err := opts.Unmarshal(w, m); err != nil { 111*1c12ee1eSDan Willemsen b.Fatal(err) 112*1c12ee1eSDan Willemsen } 113*1c12ee1eSDan Willemsen } 114*1c12ee1eSDan Willemsen }) 115*1c12ee1eSDan Willemsen }) 116*1c12ee1eSDan Willemsen b.Run("Wire/Validate", func(b *testing.B) { 117*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 118*1c12ee1eSDan Willemsen mt := (&testpb.TestAllTypes{}).ProtoReflect().Type() 119*1c12ee1eSDan Willemsen for pb.Next() { 120*1c12ee1eSDan Willemsen _, got := impl.Validate(mt, protoiface.UnmarshalInput{ 121*1c12ee1eSDan Willemsen Buf: w, 122*1c12ee1eSDan Willemsen }) 123*1c12ee1eSDan Willemsen want := impl.ValidationValid 124*1c12ee1eSDan Willemsen if got != want { 125*1c12ee1eSDan Willemsen b.Fatalf("Validate = %v, want %v", got, want) 126*1c12ee1eSDan Willemsen } 127*1c12ee1eSDan Willemsen } 128*1c12ee1eSDan Willemsen }) 129*1c12ee1eSDan Willemsen }) 130*1c12ee1eSDan Willemsen b.Run("Clone", func(b *testing.B) { 131*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 132*1c12ee1eSDan Willemsen for pb.Next() { 133*1c12ee1eSDan Willemsen proto.Clone(m) 134*1c12ee1eSDan Willemsen } 135*1c12ee1eSDan Willemsen }) 136*1c12ee1eSDan Willemsen }) 137*1c12ee1eSDan Willemsen} 138*1c12ee1eSDan Willemsen 139*1c12ee1eSDan Willemsen// BenchmarkRequired tests a message containing a required field. 140*1c12ee1eSDan Willemsenfunc BenchmarkRequired(b *testing.B) { 141*1c12ee1eSDan Willemsen m := µpb.SixteenRequired{ 142*1c12ee1eSDan Willemsen F1: proto.Int32(1), 143*1c12ee1eSDan Willemsen F2: proto.Int32(1), 144*1c12ee1eSDan Willemsen F3: proto.Int32(1), 145*1c12ee1eSDan Willemsen F4: proto.Int32(1), 146*1c12ee1eSDan Willemsen F5: proto.Int32(1), 147*1c12ee1eSDan Willemsen F6: proto.Int32(1), 148*1c12ee1eSDan Willemsen F7: proto.Int32(1), 149*1c12ee1eSDan Willemsen F8: proto.Int32(1), 150*1c12ee1eSDan Willemsen F9: proto.Int32(1), 151*1c12ee1eSDan Willemsen F10: proto.Int32(1), 152*1c12ee1eSDan Willemsen F11: proto.Int32(1), 153*1c12ee1eSDan Willemsen F12: proto.Int32(1), 154*1c12ee1eSDan Willemsen F13: proto.Int32(1), 155*1c12ee1eSDan Willemsen F14: proto.Int32(1), 156*1c12ee1eSDan Willemsen F15: proto.Int32(1), 157*1c12ee1eSDan Willemsen F16: proto.Int32(1), 158*1c12ee1eSDan Willemsen } 159*1c12ee1eSDan Willemsen w, err := proto.Marshal(m) 160*1c12ee1eSDan Willemsen if err != nil { 161*1c12ee1eSDan Willemsen b.Fatal(err) 162*1c12ee1eSDan Willemsen } 163*1c12ee1eSDan Willemsen b.Run("Wire/Marshal", func(b *testing.B) { 164*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 165*1c12ee1eSDan Willemsen for pb.Next() { 166*1c12ee1eSDan Willemsen if _, err := proto.Marshal(m); err != nil { 167*1c12ee1eSDan Willemsen b.Fatal(err) 168*1c12ee1eSDan Willemsen } 169*1c12ee1eSDan Willemsen } 170*1c12ee1eSDan Willemsen }) 171*1c12ee1eSDan Willemsen }) 172*1c12ee1eSDan Willemsen b.Run("Wire/Unmarshal", func(b *testing.B) { 173*1c12ee1eSDan Willemsen opts := proto.UnmarshalOptions{ 174*1c12ee1eSDan Willemsen Merge: true, 175*1c12ee1eSDan Willemsen } 176*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 177*1c12ee1eSDan Willemsen m := µpb.SixteenRequired{} 178*1c12ee1eSDan Willemsen for pb.Next() { 179*1c12ee1eSDan Willemsen if err := opts.Unmarshal(w, m); err != nil { 180*1c12ee1eSDan Willemsen b.Fatal(err) 181*1c12ee1eSDan Willemsen } 182*1c12ee1eSDan Willemsen } 183*1c12ee1eSDan Willemsen }) 184*1c12ee1eSDan Willemsen }) 185*1c12ee1eSDan Willemsen b.Run("Wire/Validate", func(b *testing.B) { 186*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 187*1c12ee1eSDan Willemsen mt := (µpb.SixteenRequired{}).ProtoReflect().Type() 188*1c12ee1eSDan Willemsen for pb.Next() { 189*1c12ee1eSDan Willemsen _, got := impl.Validate(mt, protoiface.UnmarshalInput{ 190*1c12ee1eSDan Willemsen Buf: w, 191*1c12ee1eSDan Willemsen }) 192*1c12ee1eSDan Willemsen want := impl.ValidationValid 193*1c12ee1eSDan Willemsen if got != want { 194*1c12ee1eSDan Willemsen b.Fatalf("Validate = %v, want %v", got, want) 195*1c12ee1eSDan Willemsen } 196*1c12ee1eSDan Willemsen } 197*1c12ee1eSDan Willemsen }) 198*1c12ee1eSDan Willemsen }) 199*1c12ee1eSDan Willemsen b.Run("Clone", func(b *testing.B) { 200*1c12ee1eSDan Willemsen b.RunParallel(func(pb *testing.PB) { 201*1c12ee1eSDan Willemsen for pb.Next() { 202*1c12ee1eSDan Willemsen proto.Clone(m) 203*1c12ee1eSDan Willemsen } 204*1c12ee1eSDan Willemsen }) 205*1c12ee1eSDan Willemsen }) 206*1c12ee1eSDan Willemsen} 207