github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/src/runtime/iface_test.go (about)

     1  // Copyright 2012 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 runtime_test
     6  
     7  import (
     8  	"runtime"
     9  	"testing"
    10  )
    11  
    12  type I1 interface {
    13  	Method1()
    14  }
    15  
    16  type I2 interface {
    17  	Method1()
    18  	Method2()
    19  }
    20  
    21  type TS uint16
    22  type TM uintptr
    23  type TL [2]uintptr
    24  
    25  func (TS) Method1() {}
    26  func (TS) Method2() {}
    27  func (TM) Method1() {}
    28  func (TM) Method2() {}
    29  func (TL) Method1() {}
    30  func (TL) Method2() {}
    31  
    32  type T8 uint8
    33  type T16 uint16
    34  type T32 uint32
    35  type T64 uint64
    36  type Tstr string
    37  type Tslice []byte
    38  
    39  func (T8) Method1()     {}
    40  func (T16) Method1()    {}
    41  func (T32) Method1()    {}
    42  func (T64) Method1()    {}
    43  func (Tstr) Method1()   {}
    44  func (Tslice) Method1() {}
    45  
    46  var (
    47  	e  interface{}
    48  	e_ interface{}
    49  	i1 I1
    50  	i2 I2
    51  	ts TS
    52  	tm TM
    53  	tl TL
    54  	ok bool
    55  )
    56  
    57  // Issue 9370
    58  func TestCmpIfaceConcreteAlloc(t *testing.T) {
    59  	if runtime.Compiler != "gc" {
    60  		t.Skip("skipping on non-gc compiler")
    61  	}
    62  
    63  	n := testing.AllocsPerRun(1, func() {
    64  		_ = e == ts
    65  		_ = i1 == ts
    66  		_ = e == 1
    67  	})
    68  
    69  	if n > 0 {
    70  		t.Fatalf("iface cmp allocs=%v; want 0", n)
    71  	}
    72  }
    73  
    74  func BenchmarkEqEfaceConcrete(b *testing.B) {
    75  	for i := 0; i < b.N; i++ {
    76  		_ = e == ts
    77  	}
    78  }
    79  
    80  func BenchmarkEqIfaceConcrete(b *testing.B) {
    81  	for i := 0; i < b.N; i++ {
    82  		_ = i1 == ts
    83  	}
    84  }
    85  
    86  func BenchmarkNeEfaceConcrete(b *testing.B) {
    87  	for i := 0; i < b.N; i++ {
    88  		_ = e != ts
    89  	}
    90  }
    91  
    92  func BenchmarkNeIfaceConcrete(b *testing.B) {
    93  	for i := 0; i < b.N; i++ {
    94  		_ = i1 != ts
    95  	}
    96  }
    97  
    98  func BenchmarkConvT2ESmall(b *testing.B) {
    99  	for i := 0; i < b.N; i++ {
   100  		e = ts
   101  	}
   102  }
   103  
   104  func BenchmarkConvT2EUintptr(b *testing.B) {
   105  	for i := 0; i < b.N; i++ {
   106  		e = tm
   107  	}
   108  }
   109  
   110  func BenchmarkConvT2ELarge(b *testing.B) {
   111  	for i := 0; i < b.N; i++ {
   112  		e = tl
   113  	}
   114  }
   115  
   116  func BenchmarkConvT2ISmall(b *testing.B) {
   117  	for i := 0; i < b.N; i++ {
   118  		i1 = ts
   119  	}
   120  }
   121  
   122  func BenchmarkConvT2IUintptr(b *testing.B) {
   123  	for i := 0; i < b.N; i++ {
   124  		i1 = tm
   125  	}
   126  }
   127  
   128  func BenchmarkConvT2ILarge(b *testing.B) {
   129  	for i := 0; i < b.N; i++ {
   130  		i1 = tl
   131  	}
   132  }
   133  
   134  func BenchmarkConvI2E(b *testing.B) {
   135  	i2 = tm
   136  	for i := 0; i < b.N; i++ {
   137  		e = i2
   138  	}
   139  }
   140  
   141  func BenchmarkConvI2I(b *testing.B) {
   142  	i2 = tm
   143  	for i := 0; i < b.N; i++ {
   144  		i1 = i2
   145  	}
   146  }
   147  
   148  func BenchmarkAssertE2T(b *testing.B) {
   149  	e = tm
   150  	for i := 0; i < b.N; i++ {
   151  		tm = e.(TM)
   152  	}
   153  }
   154  
   155  func BenchmarkAssertE2TLarge(b *testing.B) {
   156  	e = tl
   157  	for i := 0; i < b.N; i++ {
   158  		tl = e.(TL)
   159  	}
   160  }
   161  
   162  func BenchmarkAssertE2I(b *testing.B) {
   163  	e = tm
   164  	for i := 0; i < b.N; i++ {
   165  		i1 = e.(I1)
   166  	}
   167  }
   168  
   169  func BenchmarkAssertI2T(b *testing.B) {
   170  	i1 = tm
   171  	for i := 0; i < b.N; i++ {
   172  		tm = i1.(TM)
   173  	}
   174  }
   175  
   176  func BenchmarkAssertI2I(b *testing.B) {
   177  	i1 = tm
   178  	for i := 0; i < b.N; i++ {
   179  		i2 = i1.(I2)
   180  	}
   181  }
   182  
   183  func BenchmarkAssertI2E(b *testing.B) {
   184  	i1 = tm
   185  	for i := 0; i < b.N; i++ {
   186  		e = i1.(interface{})
   187  	}
   188  }
   189  
   190  func BenchmarkAssertE2E(b *testing.B) {
   191  	e = tm
   192  	for i := 0; i < b.N; i++ {
   193  		e_ = e
   194  	}
   195  }
   196  
   197  func BenchmarkAssertE2T2(b *testing.B) {
   198  	e = tm
   199  	for i := 0; i < b.N; i++ {
   200  		tm, ok = e.(TM)
   201  	}
   202  }
   203  
   204  func BenchmarkAssertE2T2Blank(b *testing.B) {
   205  	e = tm
   206  	for i := 0; i < b.N; i++ {
   207  		_, ok = e.(TM)
   208  	}
   209  }
   210  
   211  func BenchmarkAssertI2E2(b *testing.B) {
   212  	i1 = tm
   213  	for i := 0; i < b.N; i++ {
   214  		e, ok = i1.(interface{})
   215  	}
   216  }
   217  
   218  func BenchmarkAssertI2E2Blank(b *testing.B) {
   219  	i1 = tm
   220  	for i := 0; i < b.N; i++ {
   221  		_, ok = i1.(interface{})
   222  	}
   223  }
   224  
   225  func BenchmarkAssertE2E2(b *testing.B) {
   226  	e = tm
   227  	for i := 0; i < b.N; i++ {
   228  		e_, ok = e.(interface{})
   229  	}
   230  }
   231  
   232  func BenchmarkAssertE2E2Blank(b *testing.B) {
   233  	e = tm
   234  	for i := 0; i < b.N; i++ {
   235  		_, ok = e.(interface{})
   236  	}
   237  }
   238  
   239  func TestNonEscapingConvT2E(t *testing.T) {
   240  	m := make(map[interface{}]bool)
   241  	m[42] = true
   242  	if !m[42] {
   243  		t.Fatalf("42 is not present in the map")
   244  	}
   245  	if m[0] {
   246  		t.Fatalf("0 is present in the map")
   247  	}
   248  
   249  	n := testing.AllocsPerRun(1000, func() {
   250  		if m[0] {
   251  			t.Fatalf("0 is present in the map")
   252  		}
   253  	})
   254  	if n != 0 {
   255  		t.Fatalf("want 0 allocs, got %v", n)
   256  	}
   257  }
   258  
   259  func TestNonEscapingConvT2I(t *testing.T) {
   260  	m := make(map[I1]bool)
   261  	m[TM(42)] = true
   262  	if !m[TM(42)] {
   263  		t.Fatalf("42 is not present in the map")
   264  	}
   265  	if m[TM(0)] {
   266  		t.Fatalf("0 is present in the map")
   267  	}
   268  
   269  	n := testing.AllocsPerRun(1000, func() {
   270  		if m[TM(0)] {
   271  			t.Fatalf("0 is present in the map")
   272  		}
   273  	})
   274  	if n != 0 {
   275  		t.Fatalf("want 0 allocs, got %v", n)
   276  	}
   277  }
   278  
   279  func TestZeroConvT2x(t *testing.T) {
   280  	tests := []struct {
   281  		name string
   282  		fn   func()
   283  	}{
   284  		{name: "E8", fn: func() { e = eight8 }},  // any byte-sized value does not allocate
   285  		{name: "E16", fn: func() { e = zero16 }}, // zero values do not allocate
   286  		{name: "E32", fn: func() { e = zero32 }},
   287  		{name: "E64", fn: func() { e = zero64 }},
   288  		{name: "Estr", fn: func() { e = zerostr }},
   289  		{name: "Eslice", fn: func() { e = zeroslice }},
   290  		{name: "Econstflt", fn: func() { e = 99.0 }}, // constants do not allocate
   291  		{name: "Econststr", fn: func() { e = "change" }},
   292  		{name: "I8", fn: func() { i1 = eight8I }},
   293  		{name: "I16", fn: func() { i1 = zero16I }},
   294  		{name: "I32", fn: func() { i1 = zero32I }},
   295  		{name: "I64", fn: func() { i1 = zero64I }},
   296  		{name: "Istr", fn: func() { i1 = zerostrI }},
   297  		{name: "Islice", fn: func() { i1 = zerosliceI }},
   298  	}
   299  
   300  	for _, test := range tests {
   301  		t.Run(test.name, func(t *testing.T) {
   302  			n := testing.AllocsPerRun(1000, test.fn)
   303  			if n != 0 {
   304  				t.Errorf("want zero allocs, got %v", n)
   305  			}
   306  		})
   307  	}
   308  }
   309  
   310  var (
   311  	eight8  uint8 = 8
   312  	eight8I T8    = 8
   313  
   314  	zero16  uint16 = 0
   315  	zero16I T16    = 0
   316  	one16   uint16 = 1
   317  
   318  	zero32  uint32 = 0
   319  	zero32I T32    = 0
   320  	one32   uint32 = 1
   321  
   322  	zero64  uint64 = 0
   323  	zero64I T64    = 0
   324  	one64   uint64 = 1
   325  
   326  	zerostr  string = ""
   327  	zerostrI Tstr   = ""
   328  	nzstr    string = "abc"
   329  
   330  	zeroslice  []byte = nil
   331  	zerosliceI Tslice = nil
   332  	nzslice    []byte = []byte("abc")
   333  
   334  	zerobig [512]byte
   335  	nzbig   [512]byte = [512]byte{511: 1}
   336  )
   337  
   338  func BenchmarkConvT2Ezero(b *testing.B) {
   339  	b.Run("zero", func(b *testing.B) {
   340  		b.Run("16", func(b *testing.B) {
   341  			for i := 0; i < b.N; i++ {
   342  				e = zero16
   343  			}
   344  		})
   345  		b.Run("32", func(b *testing.B) {
   346  			for i := 0; i < b.N; i++ {
   347  				e = zero32
   348  			}
   349  		})
   350  		b.Run("64", func(b *testing.B) {
   351  			for i := 0; i < b.N; i++ {
   352  				e = zero64
   353  			}
   354  		})
   355  		b.Run("str", func(b *testing.B) {
   356  			for i := 0; i < b.N; i++ {
   357  				e = zerostr
   358  			}
   359  		})
   360  		b.Run("slice", func(b *testing.B) {
   361  			for i := 0; i < b.N; i++ {
   362  				e = zeroslice
   363  			}
   364  		})
   365  		b.Run("big", func(b *testing.B) {
   366  			for i := 0; i < b.N; i++ {
   367  				e = zerobig
   368  			}
   369  		})
   370  	})
   371  	b.Run("nonzero", func(b *testing.B) {
   372  		b.Run("16", func(b *testing.B) {
   373  			for i := 0; i < b.N; i++ {
   374  				e = one16
   375  			}
   376  		})
   377  		b.Run("32", func(b *testing.B) {
   378  			for i := 0; i < b.N; i++ {
   379  				e = one32
   380  			}
   381  		})
   382  		b.Run("64", func(b *testing.B) {
   383  			for i := 0; i < b.N; i++ {
   384  				e = one64
   385  			}
   386  		})
   387  		b.Run("str", func(b *testing.B) {
   388  			for i := 0; i < b.N; i++ {
   389  				e = nzstr
   390  			}
   391  		})
   392  		b.Run("slice", func(b *testing.B) {
   393  			for i := 0; i < b.N; i++ {
   394  				e = nzslice
   395  			}
   396  		})
   397  		b.Run("big", func(b *testing.B) {
   398  			for i := 0; i < b.N; i++ {
   399  				e = nzbig
   400  			}
   401  		})
   402  	})
   403  }