blob: d5ae7281d696c2dea6e6ee0240d3912ab7c9d789 [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
27const (
28 boolValue = true
29 intValue = 1 << 30
30 floatValue = 3.14159265
31 strValue = "hello world"
32
33 maxRecurseLevel = 3
34)
35
36func makeProto() *tpb.TestAllTypes {
37 m := &tpb.TestAllTypes{}
38 fillMessage(m.ProtoReflect(), 0)
39 return m
40}
41
42func fillMessage(m pref.Message, level int) {
43 if level > maxRecurseLevel {
44 return
45 }
46
Joe Tsai0fc49f82019-05-01 12:29:25 -070047 fieldDescs := m.Descriptor().Fields()
Herbie Ong8eba9ee2019-04-15 15:29:50 -070048 for i := 0; i < fieldDescs.Len(); i++ {
49 fd := fieldDescs.Get(i)
Joe Tsaiac31a352019-05-13 14:32:56 -070050 switch {
51 case fd.IsList():
Joe Tsai378c1322019-04-25 23:48:08 -070052 setList(m.Mutable(fd).List(), fd, level)
Joe Tsaiac31a352019-05-13 14:32:56 -070053 case fd.IsMap():
Joe Tsai378c1322019-04-25 23:48:08 -070054 setMap(m.Mutable(fd).Map(), fd, level)
Joe Tsaiac31a352019-05-13 14:32:56 -070055 default:
Joe Tsai378c1322019-04-25 23:48:08 -070056 setScalarField(m, fd, level)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070057 }
58 }
59}
60
Joe Tsai378c1322019-04-25 23:48:08 -070061func setScalarField(m pref.Message, fd pref.FieldDescriptor, level int) {
Herbie Ong8eba9ee2019-04-15 15:29:50 -070062 switch fd.Kind() {
63 case pref.MessageKind, pref.GroupKind:
Damien Neild91c4222019-09-04 10:46:00 -070064 val := m.NewField(fd)
65 fillMessage(val.Message(), level+1)
66 m.Set(fd, val)
Herbie Ong8eba9ee2019-04-15 15:29:50 -070067 default:
Joe Tsai378c1322019-04-25 23:48:08 -070068 m.Set(fd, scalarField(fd.Kind()))
Herbie Ong8eba9ee2019-04-15 15:29:50 -070069 }
70}
71
72func scalarField(kind pref.Kind) pref.Value {
73 switch kind {
74 case pref.BoolKind:
75 return pref.ValueOf(boolValue)
76
77 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
78 return pref.ValueOf(int32(intValue))
79
80 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
81 return pref.ValueOf(int64(intValue))
82
83 case pref.Uint32Kind, pref.Fixed32Kind:
84 return pref.ValueOf(uint32(intValue))
85
86 case pref.Uint64Kind, pref.Fixed64Kind:
87 return pref.ValueOf(uint64(intValue))
88
89 case pref.FloatKind:
90 return pref.ValueOf(float32(floatValue))
91
92 case pref.DoubleKind:
93 return pref.ValueOf(float64(floatValue))
94
95 case pref.BytesKind:
96 return pref.ValueOf([]byte(strValue))
97
98 case pref.StringKind:
99 return pref.ValueOf(strValue)
100
101 case pref.EnumKind:
102 return pref.ValueOf(pref.EnumNumber(42))
103 }
104
105 panic(fmt.Sprintf("FieldDescriptor.Kind %v is not valid", kind))
106}
107
108func setList(list pref.List, fd pref.FieldDescriptor, level int) {
109 switch fd.Kind() {
110 case pref.MessageKind, pref.GroupKind:
111 for i := 0; i < 10; i++ {
Damien Neild91c4222019-09-04 10:46:00 -0700112 val := list.NewElement()
113 fillMessage(val.Message(), level+1)
114 list.Append(val)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700115 }
116 default:
117 for i := 0; i < 100; i++ {
118 list.Append(scalarField(fd.Kind()))
119 }
120 }
121}
122
123func setMap(mmap pref.Map, fd pref.FieldDescriptor, level int) {
Joe Tsaid24bc722019-04-15 23:39:09 -0700124 fields := fd.Message().Fields()
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700125 keyDesc := fields.ByNumber(1)
126 valDesc := fields.ByNumber(2)
127
128 pkey := scalarField(keyDesc.Kind())
129 switch kind := valDesc.Kind(); kind {
130 case pref.MessageKind, pref.GroupKind:
Damien Neild91c4222019-09-04 10:46:00 -0700131 val := mmap.NewValue()
132 fillMessage(val.Message(), level+1)
133 mmap.Set(pkey.MapKey(), val)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700134 default:
135 mmap.Set(pkey.MapKey(), scalarField(kind))
136 }
137}
138
139func BenchmarkTextEncode(b *testing.B) {
140 m := makeProto()
141 for i := 0; i < b.N; i++ {
142 if *benchV1 {
143 protoV1.MarshalTextString(m)
144 } else {
Damien Neil5c5b5312019-05-14 12:44:37 -0700145 _, err := prototext.MarshalOptions{Indent: " "}.Marshal(m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700146 if err != nil {
147 b.Fatal(err)
148 }
149 }
150 }
151}
152
153func BenchmarkTextDecode(b *testing.B) {
154 m := makeProto()
Damien Neil5c5b5312019-05-14 12:44:37 -0700155 in, err := prototext.MarshalOptions{Indent: " "}.Marshal(m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700156 if err != nil {
157 b.Fatal(err)
158 }
159
160 for i := 0; i < b.N; i++ {
161 m := &tpb.TestAllTypes{}
162 var err error
163 if *benchV1 {
164 err = protoV1.UnmarshalText(string(in), m)
165 } else {
Joe Tsaicdb77732019-05-14 16:05:06 -0700166 err = prototext.Unmarshal(in, m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700167 }
168 if err != nil {
169 b.Fatal(err)
170 }
171 }
172}
173
174func BenchmarkJSONEncode(b *testing.B) {
175 m := makeProto()
176 for i := 0; i < b.N; i++ {
177 var err error
178 if *benchV1 {
179 jsm := &jsonpbV1.Marshaler{Indent: " "}
180 _, err = jsm.MarshalToString(m)
181 } else {
Damien Neil5c5b5312019-05-14 12:44:37 -0700182 _, err = protojson.MarshalOptions{Indent: " "}.Marshal(m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700183 }
184 if err != nil {
185 b.Fatal(err)
186 }
187 }
188}
189
190func BenchmarkJSONDecode(b *testing.B) {
191 m := makeProto()
Damien Neil5c5b5312019-05-14 12:44:37 -0700192 out, err := protojson.MarshalOptions{Indent: " "}.Marshal(m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700193 if err != nil {
194 b.Fatal(err)
195 }
196
197 for i := 0; i < b.N; i++ {
198 m := &tpb.TestAllTypes{}
199 var err error
200 if *benchV1 {
201 err = jsonpbV1.UnmarshalString(string(out), m)
202 } else {
Joe Tsaicdb77732019-05-14 16:05:06 -0700203 err = protojson.Unmarshal(out, m)
Herbie Ong8eba9ee2019-04-15 15:29:50 -0700204 }
205 if err != nil {
206 b.Fatal(err)
207 }
208 }
209}