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