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 BenchmarkMapsDeepEqual(b *testing.B) {
111 m1 := map[int]int{
112 1: 1, 2: 2,
113 }
114 m2 := map[int]int{
115 1: 1, 2: 2,
116 }
117 for i := 0; i < b.N; i++ {
118 DeepEqual(m1, m2)
119 }
120 }
121
122 func BenchmarkIsZero(b *testing.B) {
123 type Int4 struct {
124 a, b, c, d int
125 }
126 type Int1024 struct {
127 a [1024]int
128 }
129 type Int512 struct {
130 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 [16]S
131 }
132 s := struct {
133 ArrayComparable [4]T
134 ArrayIncomparable [4]_Complex
135 StructComparable T
136 StructIncomparable _Complex
137 ArrayInt_4 [4]int
138 ArrayInt_1024 [1024]int
139 ArrayInt_1024_NoZero [1024]int
140 Struct4Int Int4
141 ArrayStruct4Int_1024 [256]Int4
142 ArrayChanInt_1024 [1024]chan int
143 StructInt_512 Int512
144 }{}
145 s.ArrayInt_1024_NoZero[512] = 1
146 source := ValueOf(s)
147
148 for i := 0; i < source.NumField(); i++ {
149 name := source.Type().Field(i).Name
150 value := source.Field(i)
151 b.Run(name, func(b *testing.B) {
152 for i := 0; i < b.N; i++ {
153 sink = value.IsZero()
154 }
155 })
156 }
157 }
158
159 func BenchmarkSetZero(b *testing.B) {
160 source := ValueOf(new(struct {
161 Bool bool
162 Int int64
163 Uint uint64
164 Float float64
165 Complex complex128
166 Array [4]Value
167 Chan chan Value
168 Func func() Value
169 Interface interface{ String() string }
170 Map map[string]Value
171 Pointer *Value
172 Slice []Value
173 String string
174 Struct Value
175 })).Elem()
176
177 for i := 0; i < source.NumField(); i++ {
178 name := source.Type().Field(i).Name
179 value := source.Field(i)
180 zero := Zero(value.Type())
181 b.Run(name+"/Direct", func(b *testing.B) {
182 for i := 0; i < b.N; i++ {
183 value.SetZero()
184 }
185 })
186 b.Run(name+"/CachedZero", func(b *testing.B) {
187 for i := 0; i < b.N; i++ {
188 value.Set(zero)
189 }
190 })
191 b.Run(name+"/NewZero", func(b *testing.B) {
192 for i := 0; i < b.N; i++ {
193 value.Set(Zero(value.Type()))
194 }
195 })
196 }
197 }
198
199 func BenchmarkSelect(b *testing.B) {
200 channel := make(chan int)
201 close(channel)
202 var cases []SelectCase
203 for i := 0; i < 8; i++ {
204 cases = append(cases, SelectCase{
205 Dir: SelectRecv,
206 Chan: ValueOf(channel),
207 })
208 }
209 for _, numCases := range []int{1, 4, 8} {
210 b.Run(strconv.Itoa(numCases), func(b *testing.B) {
211 b.ReportAllocs()
212 for i := 0; i < b.N; i++ {
213 _, _, _ = Select(cases[:numCases])
214 }
215 })
216 }
217 }
218
219 func BenchmarkCall(b *testing.B) {
220 fv := ValueOf(func(a, b string) {})
221 b.ReportAllocs()
222 b.RunParallel(func(pb *testing.PB) {
223 args := []Value{ValueOf("a"), ValueOf("b")}
224 for pb.Next() {
225 fv.Call(args)
226 }
227 })
228 }
229
230 type myint int64
231
232 func (i *myint) inc() {
233 *i = *i + 1
234 }
235
236 func BenchmarkCallMethod(b *testing.B) {
237 b.ReportAllocs()
238 z := new(myint)
239
240 v := ValueOf(z.inc)
241 for i := 0; i < b.N; i++ {
242 v.Call(nil)
243 }
244 }
245
246 func BenchmarkCallArgCopy(b *testing.B) {
247 byteArray := func(n int) Value {
248 return Zero(ArrayOf(n, TypeOf(byte(0))))
249 }
250 sizes := [...]struct {
251 fv Value
252 arg Value
253 }{
254 {ValueOf(func(a [128]byte) {}), byteArray(128)},
255 {ValueOf(func(a [256]byte) {}), byteArray(256)},
256 {ValueOf(func(a [1024]byte) {}), byteArray(1024)},
257 {ValueOf(func(a [4096]byte) {}), byteArray(4096)},
258 {ValueOf(func(a [65536]byte) {}), byteArray(65536)},
259 }
260 for _, size := range sizes {
261 bench := func(b *testing.B) {
262 args := []Value{size.arg}
263 b.SetBytes(int64(size.arg.Len()))
264 b.ResetTimer()
265 b.RunParallel(func(pb *testing.PB) {
266 for pb.Next() {
267 size.fv.Call(args)
268 }
269 })
270 }
271 name := fmt.Sprintf("size=%v", size.arg.Len())
272 b.Run(name, bench)
273 }
274 }
275
276 func BenchmarkPtrTo(b *testing.B) {
277
278 type T struct{ int }
279 t := SliceOf(TypeOf(T{}))
280 ptrToThis := ValueOf(t).Elem().FieldByName("PtrToThis")
281 if !ptrToThis.IsValid() {
282 b.Skipf("%v has no ptrToThis field; was it removed from rtype?", t)
283
284 }
285 if ptrToThis.Int() != 0 {
286 b.Fatalf("%v.ptrToThis unexpectedly nonzero", t)
287 }
288 b.ResetTimer()
289
290
291
292 b.RunParallel(func(pb *testing.PB) {
293 for pb.Next() {
294 PointerTo(t)
295 }
296 })
297 }
298
299 type B1 struct {
300 X int
301 Y int
302 Z int
303 }
304
305 func BenchmarkFieldByName1(b *testing.B) {
306 t := TypeOf(B1{})
307 b.RunParallel(func(pb *testing.PB) {
308 for pb.Next() {
309 t.FieldByName("Z")
310 }
311 })
312 }
313
314 func BenchmarkFieldByName2(b *testing.B) {
315 t := TypeOf(S3{})
316 b.RunParallel(func(pb *testing.PB) {
317 for pb.Next() {
318 t.FieldByName("B")
319 }
320 })
321 }
322
323 func BenchmarkFieldByName3(b *testing.B) {
324 t := TypeOf(R0{})
325 b.RunParallel(func(pb *testing.PB) {
326 for pb.Next() {
327 t.FieldByName("X")
328 }
329 })
330 }
331
332 type S struct {
333 i1 int64
334 i2 int64
335 }
336
337 func BenchmarkInterfaceBig(b *testing.B) {
338 v := ValueOf(S{})
339 b.RunParallel(func(pb *testing.PB) {
340 for pb.Next() {
341 v.Interface()
342 }
343 })
344 b.StopTimer()
345 }
346
347 func BenchmarkInterfaceSmall(b *testing.B) {
348 v := ValueOf(int64(0))
349 b.RunParallel(func(pb *testing.PB) {
350 for pb.Next() {
351 v.Interface()
352 }
353 })
354 }
355
356 func BenchmarkNew(b *testing.B) {
357 v := TypeOf(XM{})
358 b.RunParallel(func(pb *testing.PB) {
359 for pb.Next() {
360 New(v)
361 }
362 })
363 }
364
365 func BenchmarkMap(b *testing.B) {
366 type V *int
367 type S string
368 value := ValueOf((V)(nil))
369 stringKeys := []string{}
370 mapOfStrings := map[string]V{}
371 uint64Keys := []uint64{}
372 mapOfUint64s := map[uint64]V{}
373 userStringKeys := []S{}
374 mapOfUserStrings := map[S]V{}
375 for i := 0; i < 100; i++ {
376 stringKey := fmt.Sprintf("key%d", i)
377 stringKeys = append(stringKeys, stringKey)
378 mapOfStrings[stringKey] = nil
379
380 uint64Key := uint64(i)
381 uint64Keys = append(uint64Keys, uint64Key)
382 mapOfUint64s[uint64Key] = nil
383
384 userStringKey := S(fmt.Sprintf("key%d", i))
385 userStringKeys = append(userStringKeys, userStringKey)
386 mapOfUserStrings[userStringKey] = nil
387 }
388
389 tests := []struct {
390 label string
391 m, keys, value Value
392 }{
393 {"StringKeys", ValueOf(mapOfStrings), ValueOf(stringKeys), value},
394 {"Uint64Keys", ValueOf(mapOfUint64s), ValueOf(uint64Keys), value},
395 {"UserStringKeys", ValueOf(mapOfUserStrings), ValueOf(userStringKeys), value},
396 }
397
398 for _, tt := range tests {
399 b.Run(tt.label, func(b *testing.B) {
400 b.Run("MapIndex", func(b *testing.B) {
401 b.ReportAllocs()
402 for i := 0; i < b.N; i++ {
403 for j := tt.keys.Len() - 1; j >= 0; j-- {
404 tt.m.MapIndex(tt.keys.Index(j))
405 }
406 }
407 })
408 b.Run("SetMapIndex", func(b *testing.B) {
409 b.ReportAllocs()
410 for i := 0; i < b.N; i++ {
411 for j := tt.keys.Len() - 1; j >= 0; j-- {
412 tt.m.SetMapIndex(tt.keys.Index(j), tt.value)
413 }
414 }
415 })
416 })
417 }
418 }
419
420 func BenchmarkMapIterNext(b *testing.B) {
421 m := ValueOf(map[string]int{"a": 0, "b": 1, "c": 2, "d": 3})
422 it := m.MapRange()
423 for i := 0; i < b.N; i++ {
424 for it.Next() {
425 }
426 it.Reset(m)
427 }
428 }
429
View as plain text