• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 := &micropb.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 := &micropb.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 := (&micropb.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