github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/bench/mispredict/iface_test.go (about) 1 package mispredict 2 3 import ( 4 "math" 5 "math/rand" 6 "sort" 7 "testing" 8 "unsafe" 9 ) 10 11 type Shape interface { 12 Area() float32 13 } 14 15 type Circle struct{ Radius float32 } 16 type Square struct{ Side float32 } 17 18 func (s Circle) Area() float32 { 19 return math.Pi * s.Radius * s.Radius 20 } 21 func (s Square) Area() float32 { 22 return s.Side * s.Side 23 } 24 25 func TotalArea(shapes []Shape) (total float32) { 26 for _, shape := range shapes { 27 total += shape.Area() 28 } 29 return total 30 } 31 32 // random shapes 33 var shapes = func() []Shape { 34 shapes := make([]Shape, 1e4) 35 for i := range shapes { 36 if rand.Intn(2) == 0 { 37 shapes[i] = Circle{rand.Float32()} 38 } else { 39 shapes[i] = Square{rand.Float32()} 40 } 41 } 42 return shapes 43 }() 44 45 func BenchmarkRandomShapes(b *testing.B) { 46 total := float32(0) 47 for k := 0; k < b.N; k++ { 48 total += TotalArea(shapes) 49 } 50 } 51 52 var sortedShapes = func() []Shape { 53 sorted := make([]Shape, len(shapes)) 54 copy(sorted, shapes) 55 56 type iface struct { 57 itab uintptr 58 data unsafe.Pointer 59 } 60 sort.Slice(sorted, func(i, k int) bool { 61 // don't do this in production 62 a := (*iface)(unsafe.Pointer(&sorted[i])).itab 63 b := (*iface)(unsafe.Pointer(&sorted[k])).itab 64 return a < b 65 }) 66 return sorted 67 }() 68 69 func BenchmarkSortedShapes(b *testing.B) { 70 total := float32(0) 71 for k := 0; k < b.N; k++ { 72 total += TotalArea(sortedShapes) 73 } 74 }