github.com/lovishpuri/go-40569/src@v0.0.0-20230519171745-f8623e7c56cf/reflect/benchmark_test.go (about)

     1  // Copyright 2022 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  
     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  	// Construct a type with a zero ptrToThis.
   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) // TODO fix this at top of refactoring
   253  		// b.Fatalf("%v has no ptrToThis field; was it removed from rtype?", t)
   254  	}
   255  	if ptrToThis.Int() != 0 {
   256  		b.Fatalf("%v.ptrToThis unexpectedly nonzero", t)
   257  	}
   258  	b.ResetTimer()
   259  
   260  	// Now benchmark calling PointerTo on it: we'll have to hit the ptrMap cache on
   261  	// every call.
   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  }