...

Source file src/runtime/iface_test.go

Documentation: runtime

		 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 BenchmarkConvT2EByteSized(b *testing.B) {
		99  	b.Run("bool", func(b *testing.B) {
	 100  		for i := 0; i < b.N; i++ {
	 101  			e = yes
	 102  		}
	 103  	})
	 104  	b.Run("uint8", func(b *testing.B) {
	 105  		for i := 0; i < b.N; i++ {
	 106  			e = eight8
	 107  		}
	 108  	})
	 109  }
	 110  
	 111  func BenchmarkConvT2ESmall(b *testing.B) {
	 112  	for i := 0; i < b.N; i++ {
	 113  		e = ts
	 114  	}
	 115  }
	 116  
	 117  func BenchmarkConvT2EUintptr(b *testing.B) {
	 118  	for i := 0; i < b.N; i++ {
	 119  		e = tm
	 120  	}
	 121  }
	 122  
	 123  func BenchmarkConvT2ELarge(b *testing.B) {
	 124  	for i := 0; i < b.N; i++ {
	 125  		e = tl
	 126  	}
	 127  }
	 128  
	 129  func BenchmarkConvT2ISmall(b *testing.B) {
	 130  	for i := 0; i < b.N; i++ {
	 131  		i1 = ts
	 132  	}
	 133  }
	 134  
	 135  func BenchmarkConvT2IUintptr(b *testing.B) {
	 136  	for i := 0; i < b.N; i++ {
	 137  		i1 = tm
	 138  	}
	 139  }
	 140  
	 141  func BenchmarkConvT2ILarge(b *testing.B) {
	 142  	for i := 0; i < b.N; i++ {
	 143  		i1 = tl
	 144  	}
	 145  }
	 146  
	 147  func BenchmarkConvI2E(b *testing.B) {
	 148  	i2 = tm
	 149  	for i := 0; i < b.N; i++ {
	 150  		e = i2
	 151  	}
	 152  }
	 153  
	 154  func BenchmarkConvI2I(b *testing.B) {
	 155  	i2 = tm
	 156  	for i := 0; i < b.N; i++ {
	 157  		i1 = i2
	 158  	}
	 159  }
	 160  
	 161  func BenchmarkAssertE2T(b *testing.B) {
	 162  	e = tm
	 163  	for i := 0; i < b.N; i++ {
	 164  		tm = e.(TM)
	 165  	}
	 166  }
	 167  
	 168  func BenchmarkAssertE2TLarge(b *testing.B) {
	 169  	e = tl
	 170  	for i := 0; i < b.N; i++ {
	 171  		tl = e.(TL)
	 172  	}
	 173  }
	 174  
	 175  func BenchmarkAssertE2I(b *testing.B) {
	 176  	e = tm
	 177  	for i := 0; i < b.N; i++ {
	 178  		i1 = e.(I1)
	 179  	}
	 180  }
	 181  
	 182  func BenchmarkAssertI2T(b *testing.B) {
	 183  	i1 = tm
	 184  	for i := 0; i < b.N; i++ {
	 185  		tm = i1.(TM)
	 186  	}
	 187  }
	 188  
	 189  func BenchmarkAssertI2I(b *testing.B) {
	 190  	i1 = tm
	 191  	for i := 0; i < b.N; i++ {
	 192  		i2 = i1.(I2)
	 193  	}
	 194  }
	 195  
	 196  func BenchmarkAssertI2E(b *testing.B) {
	 197  	i1 = tm
	 198  	for i := 0; i < b.N; i++ {
	 199  		e = i1.(interface{})
	 200  	}
	 201  }
	 202  
	 203  func BenchmarkAssertE2E(b *testing.B) {
	 204  	e = tm
	 205  	for i := 0; i < b.N; i++ {
	 206  		e_ = e
	 207  	}
	 208  }
	 209  
	 210  func BenchmarkAssertE2T2(b *testing.B) {
	 211  	e = tm
	 212  	for i := 0; i < b.N; i++ {
	 213  		tm, ok = e.(TM)
	 214  	}
	 215  }
	 216  
	 217  func BenchmarkAssertE2T2Blank(b *testing.B) {
	 218  	e = tm
	 219  	for i := 0; i < b.N; i++ {
	 220  		_, ok = e.(TM)
	 221  	}
	 222  }
	 223  
	 224  func BenchmarkAssertI2E2(b *testing.B) {
	 225  	i1 = tm
	 226  	for i := 0; i < b.N; i++ {
	 227  		e, ok = i1.(interface{})
	 228  	}
	 229  }
	 230  
	 231  func BenchmarkAssertI2E2Blank(b *testing.B) {
	 232  	i1 = tm
	 233  	for i := 0; i < b.N; i++ {
	 234  		_, ok = i1.(interface{})
	 235  	}
	 236  }
	 237  
	 238  func BenchmarkAssertE2E2(b *testing.B) {
	 239  	e = tm
	 240  	for i := 0; i < b.N; i++ {
	 241  		e_, ok = e.(interface{})
	 242  	}
	 243  }
	 244  
	 245  func BenchmarkAssertE2E2Blank(b *testing.B) {
	 246  	e = tm
	 247  	for i := 0; i < b.N; i++ {
	 248  		_, ok = e.(interface{})
	 249  	}
	 250  }
	 251  
	 252  func TestNonEscapingConvT2E(t *testing.T) {
	 253  	m := make(map[interface{}]bool)
	 254  	m[42] = true
	 255  	if !m[42] {
	 256  		t.Fatalf("42 is not present in the map")
	 257  	}
	 258  	if m[0] {
	 259  		t.Fatalf("0 is present in the map")
	 260  	}
	 261  
	 262  	n := testing.AllocsPerRun(1000, func() {
	 263  		if m[0] {
	 264  			t.Fatalf("0 is present in the map")
	 265  		}
	 266  	})
	 267  	if n != 0 {
	 268  		t.Fatalf("want 0 allocs, got %v", n)
	 269  	}
	 270  }
	 271  
	 272  func TestNonEscapingConvT2I(t *testing.T) {
	 273  	m := make(map[I1]bool)
	 274  	m[TM(42)] = true
	 275  	if !m[TM(42)] {
	 276  		t.Fatalf("42 is not present in the map")
	 277  	}
	 278  	if m[TM(0)] {
	 279  		t.Fatalf("0 is present in the map")
	 280  	}
	 281  
	 282  	n := testing.AllocsPerRun(1000, func() {
	 283  		if m[TM(0)] {
	 284  			t.Fatalf("0 is present in the map")
	 285  		}
	 286  	})
	 287  	if n != 0 {
	 288  		t.Fatalf("want 0 allocs, got %v", n)
	 289  	}
	 290  }
	 291  
	 292  func TestZeroConvT2x(t *testing.T) {
	 293  	tests := []struct {
	 294  		name string
	 295  		fn	 func()
	 296  	}{
	 297  		{name: "E8", fn: func() { e = eight8 }},	// any byte-sized value does not allocate
	 298  		{name: "E16", fn: func() { e = zero16 }}, // zero values do not allocate
	 299  		{name: "E32", fn: func() { e = zero32 }},
	 300  		{name: "E64", fn: func() { e = zero64 }},
	 301  		{name: "Estr", fn: func() { e = zerostr }},
	 302  		{name: "Eslice", fn: func() { e = zeroslice }},
	 303  		{name: "Econstflt", fn: func() { e = 99.0 }}, // constants do not allocate
	 304  		{name: "Econststr", fn: func() { e = "change" }},
	 305  		{name: "I8", fn: func() { i1 = eight8I }},
	 306  		{name: "I16", fn: func() { i1 = zero16I }},
	 307  		{name: "I32", fn: func() { i1 = zero32I }},
	 308  		{name: "I64", fn: func() { i1 = zero64I }},
	 309  		{name: "Istr", fn: func() { i1 = zerostrI }},
	 310  		{name: "Islice", fn: func() { i1 = zerosliceI }},
	 311  	}
	 312  
	 313  	for _, test := range tests {
	 314  		t.Run(test.name, func(t *testing.T) {
	 315  			n := testing.AllocsPerRun(1000, test.fn)
	 316  			if n != 0 {
	 317  				t.Errorf("want zero allocs, got %v", n)
	 318  			}
	 319  		})
	 320  	}
	 321  }
	 322  
	 323  var (
	 324  	eight8	uint8 = 8
	 325  	eight8I T8		= 8
	 326  	yes		 bool	= true
	 327  
	 328  	zero16		 uint16 = 0
	 329  	zero16I		T16		= 0
	 330  	one16			uint16 = 1
	 331  	thousand16 uint16 = 1000
	 332  
	 333  	zero32		 uint32 = 0
	 334  	zero32I		T32		= 0
	 335  	one32			uint32 = 1
	 336  	thousand32 uint32 = 1000
	 337  
	 338  	zero64		 uint64 = 0
	 339  	zero64I		T64		= 0
	 340  	one64			uint64 = 1
	 341  	thousand64 uint64 = 1000
	 342  
	 343  	zerostr	string = ""
	 344  	zerostrI Tstr	 = ""
	 345  	nzstr		string = "abc"
	 346  
	 347  	zeroslice	[]byte = nil
	 348  	zerosliceI Tslice = nil
	 349  	nzslice		[]byte = []byte("abc")
	 350  
	 351  	zerobig [512]byte
	 352  	nzbig	 [512]byte = [512]byte{511: 1}
	 353  )
	 354  
	 355  func BenchmarkConvT2Ezero(b *testing.B) {
	 356  	b.Run("zero", func(b *testing.B) {
	 357  		b.Run("16", func(b *testing.B) {
	 358  			for i := 0; i < b.N; i++ {
	 359  				e = zero16
	 360  			}
	 361  		})
	 362  		b.Run("32", func(b *testing.B) {
	 363  			for i := 0; i < b.N; i++ {
	 364  				e = zero32
	 365  			}
	 366  		})
	 367  		b.Run("64", func(b *testing.B) {
	 368  			for i := 0; i < b.N; i++ {
	 369  				e = zero64
	 370  			}
	 371  		})
	 372  		b.Run("str", func(b *testing.B) {
	 373  			for i := 0; i < b.N; i++ {
	 374  				e = zerostr
	 375  			}
	 376  		})
	 377  		b.Run("slice", func(b *testing.B) {
	 378  			for i := 0; i < b.N; i++ {
	 379  				e = zeroslice
	 380  			}
	 381  		})
	 382  		b.Run("big", func(b *testing.B) {
	 383  			for i := 0; i < b.N; i++ {
	 384  				e = zerobig
	 385  			}
	 386  		})
	 387  	})
	 388  	b.Run("nonzero", func(b *testing.B) {
	 389  		b.Run("str", func(b *testing.B) {
	 390  			for i := 0; i < b.N; i++ {
	 391  				e = nzstr
	 392  			}
	 393  		})
	 394  		b.Run("slice", func(b *testing.B) {
	 395  			for i := 0; i < b.N; i++ {
	 396  				e = nzslice
	 397  			}
	 398  		})
	 399  		b.Run("big", func(b *testing.B) {
	 400  			for i := 0; i < b.N; i++ {
	 401  				e = nzbig
	 402  			}
	 403  		})
	 404  	})
	 405  	b.Run("smallint", func(b *testing.B) {
	 406  		b.Run("16", func(b *testing.B) {
	 407  			for i := 0; i < b.N; i++ {
	 408  				e = one16
	 409  			}
	 410  		})
	 411  		b.Run("32", func(b *testing.B) {
	 412  			for i := 0; i < b.N; i++ {
	 413  				e = one32
	 414  			}
	 415  		})
	 416  		b.Run("64", func(b *testing.B) {
	 417  			for i := 0; i < b.N; i++ {
	 418  				e = one64
	 419  			}
	 420  		})
	 421  	})
	 422  	b.Run("largeint", func(b *testing.B) {
	 423  		b.Run("16", func(b *testing.B) {
	 424  			for i := 0; i < b.N; i++ {
	 425  				e = thousand16
	 426  			}
	 427  		})
	 428  		b.Run("32", func(b *testing.B) {
	 429  			for i := 0; i < b.N; i++ {
	 430  				e = thousand32
	 431  			}
	 432  		})
	 433  		b.Run("64", func(b *testing.B) {
	 434  			for i := 0; i < b.N; i++ {
	 435  				e = thousand64
	 436  			}
	 437  		})
	 438  	})
	 439  }
	 440  

View as plain text