blob: d5ac0c3930437222896605b4a6b933d18e2503a3 [file] [log] [blame]
Herbie Ong8eba9ee2019-04-15 15:29:50 -07001// 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 "flag"
9 "fmt"
10 "testing"
11
12 jsonpbV1 "github.com/golang/protobuf/jsonpb"
13 protoV1 "github.com/golang/protobuf/proto"
Damien Neil5c5b5312019-05-14 12:44:37 -070014 "google.golang.org/protobuf/encoding/protojson"
15 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -070016 pref "google.golang.org/protobuf/reflect/protoreflect"
Herbie Ong8eba9ee2019-04-15 15:29:50 -070017
Damien Neile89e6242019-05-13 23:55:40 -070018 tpb "google.golang.org/protobuf/internal/testprotos/test"
Herbie Ong8eba9ee2019-04-15 15:29:50 -070019)
20
21// The results of these microbenchmarks are unlikely to correspond well
22// to real world peformance. They are mainly useful as a quick check to
23// detect unexpected regressions and for profiling specific cases.
24
25var benchV1 = flag.Bool("v1", false, "benchmark the v1 implementation")
26
Joe Tsai84177c92019-09-17 13:38:48 -070027const maxRecurseLevel = 3
Herbie Ong8eba9ee2019-04-15 15:29:50 -070028
29func makeProto() *tpb.TestAllTypes {
30 m := &tpb.TestAllTypes{}
31 fillMessage(m.ProtoReflect(), 0)
32 return m
33}
34
35func fillMessage(m pref.Message, level int) {
36 if level > maxRecurseLevel {
37 return
38 }
39
Joe Tsai0fc49f82019-05-01 12:29:25 -070040 fieldDescs := m.Descriptor().Fields()
Herbie Ong8eba9ee2019-04-15 15:29:50 -070041 for i := 0; i < fieldDescs.Len(); i++ {
42 fd := fieldDescs.Get(i)
Joe Tsaiac31a352019-05-13 14:32:56 -070043 switch {
44 case fd.IsList():
Joe Tsai378c1322019-04-25 23:48:08 -070045 setList(m.Mutable(fd).List(), fd, level)
Joe Tsaiac31a352019-05-13 14:32:56 -070046 case fd.IsMap():
Joe Tsai378c1322019-04-25 23:48:08 -070047 setMap(m.Mutable(fd).Map(), fd, level)
Joe Tsaiac31a352019-05-13 14:32:56 -070048 default:
Joe Tsai378c1322019-04-25 23:48:08 -070049 setScalarField(m, fd, level)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070050 }
51 }
52}
53
Joe Tsai378c1322019-04-25 23:48:08 -070054func setScalarField(m pref.Message, fd pref.FieldDescriptor, level int) {
Herbie Ong8eba9ee2019-04-15 15:29:50 -070055 switch fd.Kind() {
56 case pref.MessageKind, pref.GroupKind:
Damien Neild91c4222019-09-04 10:46:00 -070057 val := m.NewField(fd)
58 fillMessage(val.Message(), level+1)
59 m.Set(fd, val)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070060 default:
Joe Tsai378c1322019-04-25 23:48:08 -070061 m.Set(fd, scalarField(fd.Kind()))
Herbie Ong8eba9ee2019-04-15 15:29:50 -070062 }
63}
64
65func scalarField(kind pref.Kind) pref.Value {
66 switch kind {
67 case pref.BoolKind:
Joe Tsai84177c92019-09-17 13:38:48 -070068 return pref.ValueOfBool(true)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070069
70 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
Joe Tsai84177c92019-09-17 13:38:48 -070071 return pref.ValueOfInt32(1 << 30)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070072
73 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
Joe Tsai84177c92019-09-17 13:38:48 -070074 return pref.ValueOfInt64(1 << 30)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070075
76 case pref.Uint32Kind, pref.Fixed32Kind:
Joe Tsai84177c92019-09-17 13:38:48 -070077 return pref.ValueOfUint32(1 << 30)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070078
79 case pref.Uint64Kind, pref.Fixed64Kind:
Joe Tsai84177c92019-09-17 13:38:48 -070080 return pref.ValueOfUint64(1 << 30)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070081
82 case pref.FloatKind:
Joe Tsai84177c92019-09-17 13:38:48 -070083 return pref.ValueOfFloat32(3.14159265)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070084
85 case pref.DoubleKind:
Joe Tsai84177c92019-09-17 13:38:48 -070086 return pref.ValueOfFloat64(3.14159265)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070087
88 case pref.BytesKind:
Joe Tsai84177c92019-09-17 13:38:48 -070089 return pref.ValueOfBytes([]byte("hello world"))
Herbie Ong8eba9ee2019-04-15 15:29:50 -070090
91 case pref.StringKind:
Joe Tsai84177c92019-09-17 13:38:48 -070092 return pref.ValueOfString("hello world")
Herbie Ong8eba9ee2019-04-15 15:29:50 -070093
94 case pref.EnumKind:
Joe Tsai84177c92019-09-17 13:38:48 -070095 return pref.ValueOfEnum(42)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070096 }
97
98 panic(fmt.Sprintf("FieldDescriptor.Kind %v is not valid", kind))
99}
100
101func setList(list pref.List, fd pref.FieldDescriptor, level int) {
102 switch fd.Kind() {
103 case pref.MessageKind, pref.GroupKind:
104 for i := 0; i < 10; i++ {
Damien Neild91c4222019-09-04 10:46:00 -0700105 val := list.NewElement()
106 fillMessage(val.Message(), level+1)
107 list.Append(val)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700108 }
109 default:
110 for i := 0; i < 100; i++ {
111 list.Append(scalarField(fd.Kind()))
112 }
113 }
114}
115
116func setMap(mmap pref.Map, fd pref.FieldDescriptor, level int) {
Joe Tsaid24bc722019-04-15 23:39:09 -0700117 fields := fd.Message().Fields()
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700118 keyDesc := fields.ByNumber(1)
119 valDesc := fields.ByNumber(2)
120
121 pkey := scalarField(keyDesc.Kind())
122 switch kind := valDesc.Kind(); kind {
123 case pref.MessageKind, pref.GroupKind:
Damien Neild91c4222019-09-04 10:46:00 -0700124 val := mmap.NewValue()
125 fillMessage(val.Message(), level+1)
126 mmap.Set(pkey.MapKey(), val)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700127 default:
128 mmap.Set(pkey.MapKey(), scalarField(kind))
129 }
130}
131
132func BenchmarkTextEncode(b *testing.B) {
133 m := makeProto()
134 for i := 0; i < b.N; i++ {
135 if *benchV1 {
136 protoV1.MarshalTextString(m)
137 } else {
Damien Neil5c5b5312019-05-14 12:44:37 -0700138 _, err := prototext.MarshalOptions{Indent: " "}.Marshal(m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700139 if err != nil {
140 b.Fatal(err)
141 }
142 }
143 }
144}
145
146func BenchmarkTextDecode(b *testing.B) {
147 m := makeProto()
Damien Neil5c5b5312019-05-14 12:44:37 -0700148 in, err := prototext.MarshalOptions{Indent: " "}.Marshal(m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700149 if err != nil {
150 b.Fatal(err)
151 }
152
153 for i := 0; i < b.N; i++ {
154 m := &tpb.TestAllTypes{}
155 var err error
156 if *benchV1 {
157 err = protoV1.UnmarshalText(string(in), m)
158 } else {
Joe Tsaicdb77732019-05-14 16:05:06 -0700159 err = prototext.Unmarshal(in, m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700160 }
161 if err != nil {
162 b.Fatal(err)
163 }
164 }
165}
166
167func BenchmarkJSONEncode(b *testing.B) {
168 m := makeProto()
169 for i := 0; i < b.N; i++ {
170 var err error
171 if *benchV1 {
172 jsm := &jsonpbV1.Marshaler{Indent: " "}
173 _, err = jsm.MarshalToString(m)
174 } else {
Damien Neil5c5b5312019-05-14 12:44:37 -0700175 _, err = protojson.MarshalOptions{Indent: " "}.Marshal(m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700176 }
177 if err != nil {
178 b.Fatal(err)
179 }
180 }
181}
182
183func BenchmarkJSONDecode(b *testing.B) {
184 m := makeProto()
Damien Neil5c5b5312019-05-14 12:44:37 -0700185 out, err := protojson.MarshalOptions{Indent: " "}.Marshal(m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700186 if err != nil {
187 b.Fatal(err)
188 }
189
190 for i := 0; i < b.N; i++ {
191 m := &tpb.TestAllTypes{}
192 var err error
193 if *benchV1 {
194 err = jsonpbV1.UnmarshalString(string(out), m)
195 } else {
Joe Tsaicdb77732019-05-14 16:05:06 -0700196 err = protojson.Unmarshal(out, m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700197 }
198 if err != nil {
199 b.Fatal(err)
200 }
201 }
202}