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  }