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 }