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} 71 72// BenchmarkRepeatedInt32 tests a message containing 500 non-packed repeated int32s. 73// 74// For unmarshal operations, it measures the cost of the field decode loop, since each 75// item in the repeated field has an individual tag and value. 76func BenchmarkRepeatedInt32(b *testing.B) { 77 m := &testpb.TestAllTypes{} 78 for i := int32(0); i < 500; i++ { 79 m.RepeatedInt32 = append(m.RepeatedInt32, i) 80 } 81 w, err := proto.Marshal(m) 82 if err != nil { 83 b.Fatal(err) 84 } 85 b.Run("Wire/Marshal", func(b *testing.B) { 86 b.RunParallel(func(pb *testing.PB) { 87 for pb.Next() { 88 if _, err := proto.Marshal(m); err != nil { 89 b.Fatal(err) 90 } 91 } 92 }) 93 }) 94 b.Run("Wire/Unmarshal", func(b *testing.B) { 95 opts := proto.UnmarshalOptions{ 96 Merge: true, 97 } 98 b.RunParallel(func(pb *testing.PB) { 99 m := &testpb.TestAllTypes{} 100 for pb.Next() { 101 m.RepeatedInt32 = m.RepeatedInt32[:0] 102 if err := opts.Unmarshal(w, m); err != nil { 103 b.Fatal(err) 104 } 105 } 106 }) 107 }) 108 b.Run("Wire/Validate", func(b *testing.B) { 109 b.RunParallel(func(pb *testing.PB) { 110 mt := (&testpb.TestAllTypes{}).ProtoReflect().Type() 111 for pb.Next() { 112 _, got := impl.Validate(mt, protoiface.UnmarshalInput{ 113 Buf: w, 114 }) 115 want := impl.ValidationValid 116 if got != want { 117 b.Fatalf("Validate = %v, want %v", got, want) 118 } 119 } 120 }) 121 }) 122 b.Run("Clone", func(b *testing.B) { 123 b.RunParallel(func(pb *testing.PB) { 124 for pb.Next() { 125 proto.Clone(m) 126 } 127 }) 128 }) 129} 130 131// BenchmarkRequired tests a message containing a required field. 132func BenchmarkRequired(b *testing.B) { 133 m := µpb.SixteenRequired{ 134 F1: proto.Int32(1), 135 F2: proto.Int32(1), 136 F3: proto.Int32(1), 137 F4: proto.Int32(1), 138 F5: proto.Int32(1), 139 F6: proto.Int32(1), 140 F7: proto.Int32(1), 141 F8: proto.Int32(1), 142 F9: proto.Int32(1), 143 F10: proto.Int32(1), 144 F11: proto.Int32(1), 145 F12: proto.Int32(1), 146 F13: proto.Int32(1), 147 F14: proto.Int32(1), 148 F15: proto.Int32(1), 149 F16: proto.Int32(1), 150 } 151 w, err := proto.Marshal(m) 152 if err != nil { 153 b.Fatal(err) 154 } 155 b.Run("Wire/Marshal", func(b *testing.B) { 156 b.RunParallel(func(pb *testing.PB) { 157 for pb.Next() { 158 if _, err := proto.Marshal(m); err != nil { 159 b.Fatal(err) 160 } 161 } 162 }) 163 }) 164 b.Run("Wire/Unmarshal", func(b *testing.B) { 165 opts := proto.UnmarshalOptions{ 166 Merge: true, 167 } 168 b.RunParallel(func(pb *testing.PB) { 169 m := µpb.SixteenRequired{} 170 for pb.Next() { 171 if err := opts.Unmarshal(w, m); err != nil { 172 b.Fatal(err) 173 } 174 } 175 }) 176 }) 177 b.Run("Wire/Validate", func(b *testing.B) { 178 b.RunParallel(func(pb *testing.PB) { 179 mt := (µpb.SixteenRequired{}).ProtoReflect().Type() 180 for pb.Next() { 181 _, got := impl.Validate(mt, protoiface.UnmarshalInput{ 182 Buf: w, 183 }) 184 want := impl.ValidationValid 185 if got != want { 186 b.Fatalf("Validate = %v, want %v", got, want) 187 } 188 } 189 }) 190 }) 191 b.Run("Clone", func(b *testing.B) { 192 b.RunParallel(func(pb *testing.PB) { 193 for pb.Next() { 194 proto.Clone(m) 195 } 196 }) 197 }) 198} 199