xref: /aosp_15_r20/external/golang-protobuf/encoding/bench_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1// Copyright 2018 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
5package encoding_test
6
7import (
8	"fmt"
9	"testing"
10
11	"google.golang.org/protobuf/encoding/protojson"
12	"google.golang.org/protobuf/encoding/prototext"
13	"google.golang.org/protobuf/reflect/protoreflect"
14
15	tpb "google.golang.org/protobuf/internal/testprotos/test"
16)
17
18// The results of these microbenchmarks are unlikely to correspond well
19// to real world performance. They are mainly useful as a quick check to
20// detect unexpected regressions and for profiling specific cases.
21
22const maxRecurseLevel = 3
23
24func makeProto() *tpb.TestAllTypes {
25	m := &tpb.TestAllTypes{}
26	fillMessage(m.ProtoReflect(), 0)
27	return m
28}
29
30func fillMessage(m protoreflect.Message, level int) {
31	if level > maxRecurseLevel {
32		return
33	}
34
35	fieldDescs := m.Descriptor().Fields()
36	for i := 0; i < fieldDescs.Len(); i++ {
37		fd := fieldDescs.Get(i)
38		switch {
39		case fd.IsList():
40			setList(m.Mutable(fd).List(), fd, level)
41		case fd.IsMap():
42			setMap(m.Mutable(fd).Map(), fd, level)
43		default:
44			setScalarField(m, fd, level)
45		}
46	}
47}
48
49func setScalarField(m protoreflect.Message, fd protoreflect.FieldDescriptor, level int) {
50	switch fd.Kind() {
51	case protoreflect.MessageKind, protoreflect.GroupKind:
52		val := m.NewField(fd)
53		fillMessage(val.Message(), level+1)
54		m.Set(fd, val)
55	default:
56		m.Set(fd, scalarField(fd.Kind()))
57	}
58}
59
60func scalarField(kind protoreflect.Kind) protoreflect.Value {
61	switch kind {
62	case protoreflect.BoolKind:
63		return protoreflect.ValueOfBool(true)
64
65	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
66		return protoreflect.ValueOfInt32(1 << 30)
67
68	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
69		return protoreflect.ValueOfInt64(1 << 30)
70
71	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
72		return protoreflect.ValueOfUint32(1 << 30)
73
74	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
75		return protoreflect.ValueOfUint64(1 << 30)
76
77	case protoreflect.FloatKind:
78		return protoreflect.ValueOfFloat32(3.14159265)
79
80	case protoreflect.DoubleKind:
81		return protoreflect.ValueOfFloat64(3.14159265)
82
83	case protoreflect.BytesKind:
84		return protoreflect.ValueOfBytes([]byte("hello world"))
85
86	case protoreflect.StringKind:
87		return protoreflect.ValueOfString("hello world")
88
89	case protoreflect.EnumKind:
90		return protoreflect.ValueOfEnum(42)
91	}
92
93	panic(fmt.Sprintf("FieldDescriptor.Kind %v is not valid", kind))
94}
95
96func setList(list protoreflect.List, fd protoreflect.FieldDescriptor, level int) {
97	switch fd.Kind() {
98	case protoreflect.MessageKind, protoreflect.GroupKind:
99		for i := 0; i < 10; i++ {
100			val := list.NewElement()
101			fillMessage(val.Message(), level+1)
102			list.Append(val)
103		}
104	default:
105		for i := 0; i < 100; i++ {
106			list.Append(scalarField(fd.Kind()))
107		}
108	}
109}
110
111func setMap(mmap protoreflect.Map, fd protoreflect.FieldDescriptor, level int) {
112	fields := fd.Message().Fields()
113	keyDesc := fields.ByNumber(1)
114	valDesc := fields.ByNumber(2)
115
116	pkey := scalarField(keyDesc.Kind())
117	switch kind := valDesc.Kind(); kind {
118	case protoreflect.MessageKind, protoreflect.GroupKind:
119		val := mmap.NewValue()
120		fillMessage(val.Message(), level+1)
121		mmap.Set(pkey.MapKey(), val)
122	default:
123		mmap.Set(pkey.MapKey(), scalarField(kind))
124	}
125}
126
127func BenchmarkTextEncode(b *testing.B) {
128	m := makeProto()
129	for i := 0; i < b.N; i++ {
130		_, err := prototext.MarshalOptions{Indent: "  "}.Marshal(m)
131		if err != nil {
132			b.Fatal(err)
133		}
134	}
135}
136
137func BenchmarkTextDecode(b *testing.B) {
138	m := makeProto()
139	in, err := prototext.MarshalOptions{Indent: "  "}.Marshal(m)
140	if err != nil {
141		b.Fatal(err)
142	}
143
144	for i := 0; i < b.N; i++ {
145		m := &tpb.TestAllTypes{}
146		if err := prototext.Unmarshal(in, m); err != nil {
147			b.Fatal(err)
148		}
149	}
150}
151
152func BenchmarkJSONEncode(b *testing.B) {
153	m := makeProto()
154	for i := 0; i < b.N; i++ {
155		_, err := protojson.MarshalOptions{Indent: "  "}.Marshal(m)
156		if err != nil {
157			b.Fatal(err)
158		}
159	}
160}
161
162func BenchmarkJSONDecode(b *testing.B) {
163	m := makeProto()
164	out, err := protojson.MarshalOptions{Indent: "  "}.Marshal(m)
165	if err != nil {
166		b.Fatal(err)
167	}
168
169	for i := 0; i < b.N; i++ {
170		m := &tpb.TestAllTypes{}
171		if err := protojson.Unmarshal(out, m); err != nil {
172			b.Fatal(err)
173		}
174	}
175}
176