Source file
src/reflect/benchmark_test.go
1
2
3
4
5 package reflect_test
6
7 import (
8 "fmt"
9 . "reflect"
10 "strconv"
11 "testing"
12 )
13
14 var sourceAll = struct {
15 Bool Value
16 String Value
17 Bytes Value
18 NamedBytes Value
19 BytesArray Value
20 SliceAny Value
21 MapStringAny Value
22 }{
23 Bool: ValueOf(new(bool)).Elem(),
24 String: ValueOf(new(string)).Elem(),
25 Bytes: ValueOf(new([]byte)).Elem(),
26 NamedBytes: ValueOf(new(namedBytes)).Elem(),
27 BytesArray: ValueOf(new([32]byte)).Elem(),
28 SliceAny: ValueOf(new([]any)).Elem(),
29 MapStringAny: ValueOf(new(map[string]any)).Elem(),
30 }
31
32 var sinkAll struct {
33 RawBool bool
34 RawString string
35 RawBytes []byte
36 RawInt int
37 }
38
39 func BenchmarkBool(b *testing.B) {
40 for i := 0; i < b.N; i++ {
41 sinkAll.RawBool = sourceAll.Bool.Bool()
42 }
43 }
44
45 func BenchmarkString(b *testing.B) {
46 for i := 0; i < b.N; i++ {
47 sinkAll.RawString = sourceAll.String.String()
48 }
49 }
50
51 func BenchmarkBytes(b *testing.B) {
52 for i := 0; i < b.N; i++ {
53 sinkAll.RawBytes = sourceAll.Bytes.Bytes()
54 }
55 }
56
57 func BenchmarkNamedBytes(b *testing.B) {
58 for i := 0; i < b.N; i++ {
59 sinkAll.RawBytes = sourceAll.NamedBytes.Bytes()
60 }
61 }
62
63 func BenchmarkBytesArray(b *testing.B) {
64 for i := 0; i < b.N; i++ {
65 sinkAll.RawBytes = sourceAll.BytesArray.Bytes()
66 }
67 }
68
69 func BenchmarkSliceLen(b *testing.B) {
70 for i := 0; i < b.N; i++ {
71 sinkAll.RawInt = sourceAll.SliceAny.Len()
72 }
73 }
74
75 func BenchmarkMapLen(b *testing.B) {
76 for i := 0; i < b.N; i++ {
77 sinkAll.RawInt = sourceAll.MapStringAny.Len()
78 }
79 }
80
81 func BenchmarkStringLen(b *testing.B) {
82 for i := 0; i < b.N; i++ {
83 sinkAll.RawInt = sourceAll.String.Len()
84 }
85 }
86
87 func BenchmarkArrayLen(b *testing.B) {
88 for i := 0; i < b.N; i++ {
89 sinkAll.RawInt = sourceAll.BytesArray.Len()
90 }
91 }
92
93 func BenchmarkSliceCap(b *testing.B) {
94 for i := 0; i < b.N; i++ {
95 sinkAll.RawInt = sourceAll.SliceAny.Cap()
96 }
97 }
98
99 func BenchmarkDeepEqual(b *testing.B) {
100 for _, bb := range deepEqualPerfTests {
101 b.Run(ValueOf(bb.x).Type().String(), func(b *testing.B) {
102 b.ReportAllocs()
103 for i := 0; i < b.N; i++ {
104 sink = DeepEqual(bb.x, bb.y)
105 }
106 })
107 }
108 }
109
110 func BenchmarkIsZero(b *testing.B) {
111 source := ValueOf(struct {
112 ArrayComparable [4]T
113 ArrayIncomparable [4]_Complex
114 StructComparable T
115 StructIncomparable _Complex
116 }{})
117
118 for i := 0; i < source.NumField(); i++ {
119 name := source.Type().Field(i).Name
120 value := source.Field(i)
121 b.Run(name, func(b *testing.B) {
122 for i := 0; i < b.N; i++ {
123 sink = value.IsZero()
124 }
125 })
126 }
127 }
128
129 func BenchmarkSetZero(b *testing.B) {
130 source := ValueOf(new(struct {
131 Bool bool
132 Int int64
133 Uint uint64
134 Float float64
135 Complex complex128
136 Array [4]Value
137 Chan chan Value
138 Func func() Value
139 Interface interface{ String() string }
140 Map map[string]Value
141 Pointer *Value
142 Slice []Value
143 String string
144 Struct Value
145 })).Elem()
146
147 for i := 0; i < source.NumField(); i++ {
148 name := source.Type().Field(i).Name
149 value := source.Field(i)
150 zero := Zero(value.Type())
151 b.Run(name+"/Direct", func(b *testing.B) {
152 for i := 0; i < b.N; i++ {
153 value.SetZero()
154 }
155 })
156 b.Run(name+"/CachedZero", func(b *testing.B) {
157 for i := 0; i < b.N; i++ {
158 value.Set(zero)
159 }
160 })
161 b.Run(name+"/NewZero", func(b *testing.B) {
162 for i := 0; i < b.N; i++ {
163 value.Set(Zero(value.Type()))
164 }
165 })
166 }
167 }
168
169 func BenchmarkSelect(b *testing.B) {
170 channel := make(chan int)
171 close(channel)
172 var cases []SelectCase
173 for i := 0; i < 8; i++ {
174 cases = append(cases, SelectCase{
175 Dir: SelectRecv,
176 Chan: ValueOf(channel),
177 })
178 }
179 for _, numCases := range []int{1, 4, 8} {
180 b.Run(strconv.Itoa(numCases), func(b *testing.B) {
181 b.ReportAllocs()
182 for i := 0; i < b.N; i++ {
183 _, _, _ = Select(cases[:numCases])
184 }
185 })
186 }
187 }
188
189 func BenchmarkCall(b *testing.B) {
190 fv := ValueOf(func(a, b string) {})
191 b.ReportAllocs()
192 b.RunParallel(func(pb *testing.PB) {
193 args := []Value{ValueOf("a"), ValueOf("b")}
194 for pb.Next() {
195 fv.Call(args)
196 }
197 })
198 }
199
200 type myint int64
201
202 func (i *myint) inc() {
203 *i = *i + 1
204 }
205
206 func BenchmarkCallMethod(b *testing.B) {
207 b.ReportAllocs()
208 z := new(myint)
209
210 v := ValueOf(z.inc)
211 for i := 0; i < b.N; i++ {
212 v.Call(nil)
213 }
214 }
215
216 func BenchmarkCallArgCopy(b *testing.B) {
217 byteArray := func(n int) Value {
218 return Zero(ArrayOf(n, TypeOf(byte(0))))
219 }
220 sizes := [...]struct {
221 fv Value
222 arg Value
223 }{
224 {ValueOf(func(a [128]byte) {}), byteArray(128)},
225 {ValueOf(func(a [256]byte) {}), byteArray(256)},
226 {ValueOf(func(a [1024]byte) {}), byteArray(1024)},
227 {ValueOf(func(a [4096]byte) {}), byteArray(4096)},
228 {ValueOf(func(a [65536]byte) {}), byteArray(65536)},
229 }
230 for _, size := range sizes {
231 bench := func(b *testing.B) {
232 args := []Value{size.arg}
233 b.SetBytes(int64(size.arg.Len()))
234 b.ResetTimer()
235 b.RunParallel(func(pb *testing.PB) {
236 for pb.Next() {
237 size.fv.Call(args)
238 }
239 })
240 }
241 name := fmt.Sprintf("size=%v", size.arg.Len())
242 b.Run(name, bench)
243 }
244 }
245
246 func BenchmarkPtrTo(b *testing.B) {
247
248 type T struct{ int }
249 t := SliceOf(TypeOf(T{}))
250 ptrToThis := ValueOf(t).Elem().FieldByName("PtrToThis")
251 if !ptrToThis.IsValid() {
252 b.Skipf("%v has no ptrToThis field; was it removed from rtype?", t)
253
254 }
255 if ptrToThis.Int() != 0 {
256 b.Fatalf("%v.ptrToThis unexpectedly nonzero", t)
257 }
258 b.ResetTimer()
259
260
261
262 b.RunParallel(func(pb *testing.PB) {
263 for pb.Next() {
264 PointerTo(t)
265 }
266 })
267 }
268
269 type B1 struct {
270 X int
271 Y int
272 Z int
273 }
274
275 func BenchmarkFieldByName1(b *testing.B) {
276 t := TypeOf(B1{})
277 b.RunParallel(func(pb *testing.PB) {
278 for pb.Next() {
279 t.FieldByName("Z")
280 }
281 })
282 }
283
284 func BenchmarkFieldByName2(b *testing.B) {
285 t := TypeOf(S3{})
286 b.RunParallel(func(pb *testing.PB) {
287 for pb.Next() {
288 t.FieldByName("B")
289 }
290 })
291 }
292
293 func BenchmarkFieldByName3(b *testing.B) {
294 t := TypeOf(R0{})
295 b.RunParallel(func(pb *testing.PB) {
296 for pb.Next() {
297 t.FieldByName("X")
298 }
299 })
300 }
301
302 type S struct {
303 i1 int64
304 i2 int64
305 }
306
307 func BenchmarkInterfaceBig(b *testing.B) {
308 v := ValueOf(S{})
309 b.RunParallel(func(pb *testing.PB) {
310 for pb.Next() {
311 v.Interface()
312 }
313 })
314 b.StopTimer()
315 }
316
317 func BenchmarkInterfaceSmall(b *testing.B) {
318 v := ValueOf(int64(0))
319 b.RunParallel(func(pb *testing.PB) {
320 for pb.Next() {
321 v.Interface()
322 }
323 })
324 }
325
326 func BenchmarkNew(b *testing.B) {
327 v := TypeOf(XM{})
328 b.RunParallel(func(pb *testing.PB) {
329 for pb.Next() {
330 New(v)
331 }
332 })
333 }
334
335 func BenchmarkMap(b *testing.B) {
336 type V *int
337 type S string
338 value := ValueOf((V)(nil))
339 stringKeys := []string{}
340 mapOfStrings := map[string]V{}
341 uint64Keys := []uint64{}
342 mapOfUint64s := map[uint64]V{}
343 userStringKeys := []S{}
344 mapOfUserStrings := map[S]V{}
345 for i := 0; i < 100; i++ {
346 stringKey := fmt.Sprintf("key%d", i)
347 stringKeys = append(stringKeys, stringKey)
348 mapOfStrings[stringKey] = nil
349
350 uint64Key := uint64(i)
351 uint64Keys = append(uint64Keys, uint64Key)
352 mapOfUint64s[uint64Key] = nil
353
354 userStringKey := S(fmt.Sprintf("key%d", i))
355 userStringKeys = append(userStringKeys, userStringKey)
356 mapOfUserStrings[userStringKey] = nil
357 }
358
359 tests := []struct {
360 label string
361 m, keys, value Value
362 }{
363 {"StringKeys", ValueOf(mapOfStrings), ValueOf(stringKeys), value},
364 {"Uint64Keys", ValueOf(mapOfUint64s), ValueOf(uint64Keys), value},
365 {"UserStringKeys", ValueOf(mapOfUserStrings), ValueOf(userStringKeys), value},
366 }
367
368 for _, tt := range tests {
369 b.Run(tt.label, func(b *testing.B) {
370 b.Run("MapIndex", func(b *testing.B) {
371 b.ReportAllocs()
372 for i := 0; i < b.N; i++ {
373 for j := tt.keys.Len() - 1; j >= 0; j-- {
374 tt.m.MapIndex(tt.keys.Index(j))
375 }
376 }
377 })
378 b.Run("SetMapIndex", func(b *testing.B) {
379 b.ReportAllocs()
380 for i := 0; i < b.N; i++ {
381 for j := tt.keys.Len() - 1; j >= 0; j-- {
382 tt.m.SetMapIndex(tt.keys.Index(j), tt.value)
383 }
384 }
385 })
386 })
387 }
388 }
389
390 func BenchmarkMapIterNext(b *testing.B) {
391 m := ValueOf(map[string]int{"a": 0, "b": 1, "c": 2, "d": 3})
392 it := m.MapRange()
393 for i := 0; i < b.N; i++ {
394 for it.Next() {
395 }
396 it.Reset(m)
397 }
398 }
399
View as plain text