xref: /aosp_15_r20/external/golang-protobuf/internal/benchmarks/micro/micro_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
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 := &micropb.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 := &micropb.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 := (&micropb.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