Skip to content

Instantly share code, notes, and snippets.

@bprosnitz
Last active January 12, 2016 00:05
Show Gist options
  • Save bprosnitz/67219a1ad61f39fdd860 to your computer and use it in GitHub Desktop.
Save bprosnitz/67219a1ad61f39fdd860 to your computer and use it in GitHub Desktop.
Go benchmarks
//Put this file in $GOPATH/perfbench/perfbench_test.go
//go test -bench . -v perfbench/...
//
//go version go1.5.1 linux/amd64
//
//noop: 0
//var x interface{} = <int8>: 1
//var x interface{} = <*int8>: 0
//var x interface{} = <[]int16>: 1
//var x interface{} = <typedInterface(ptr)>: 0
//func(consts,in,vararg,list): 1
//func(preallocVarArgs...): 0
//local escape analysis (pass pointer to int as arg): 0
//local escape analysis (return pointer to int as out arg): 0
//return &int(5): 1
//return &slice[0]: 0
//return &(xint8)slice[0]: 1
//return &array[0]: 0
//return &astruct.field: 0
//return &map[1]: 1
//call with closure: 0
//
//BenchmarkLoopOverTypes-12 2000000000 0.03 ns/op
//BenchmarkTypeSwitch-12 2000000000 0.07 ns/op
//BenchmarkReflectTypeSwitch-12 2000000000 0.29 ns/op
//BenchmarkStructPtrFunctionCall-12 2000000000 0.02 ns/op
//BenchmarkInterfaceFunctionCall-12 2000000000 0.09 ns/op
//BenchmarkSingleArgFunctionCall-12 1000000000 0.03 ns/op
//BenchmarkMultiArgFunctionCall-12 1000000000 0.03 ns/op
//BenchmarkStructArgFunctionCall-12 2000000000 0.05 ns/op
//BenchmarkMultiOutArgFunctionCall-12 2000000000 0.07 ns/op
//BenchmarkStructOutArgFunctionCall-12 2000000000 0.08 ns/op
//BenchmarkReturnNumberThroughInterfaceFunctionCall-12 1 6271513094 ns/op
//BenchmarkSingleUseIntInInterface-12 1 1242256449 ns/op
//BenchmarkReuseIntInInterface-12 1 5751215766 ns/op
//
package perfbench_test
import (
"testing"
"os"
"fmt"
"reflect"
"text/tabwriter"
)
type typedInterface interface{}
type astruct struct {
A int
}
type xint8 int8
func TestAllocations(t *testing.T) {
a := astruct{4}
var v int8
ptr := &v
slc := []int16{9}
var z []int8
prealloc := []int8{3,4,5}
mmap := map[int]string{1:"one"}
var arr [4]int8
var setIndex func(int)
tests := []struct{
name string
f func() interface{}
}{
{
"noop",
func () interface{} { return nil },
},
{
"var x interface{} = <int8>",
func () interface{} {
return 1
},
},
{
"var x interface{} = <*int8>",
func () interface{} {
return ptr
},
},
{
"var x interface{} = <[]int16>",
func () interface{} {
return slc
},
},
{
"var x interface{} = <typedInterface(ptr)>",
func () interface{} {
return typedInterface(ptr)
},
},
{
"func(consts,in,vararg,list)",
func () interface{} {
z = va(1,2,3,4)
return nil
},
},
{
"func(preallocVarArgs...)",
func () interface{} {
z = va(prealloc...)
return nil
},
},
{
"local escape analysis (pass pointer to int as arg)",
func () interface{} {
x := 9
SetX(&x)
return nil
},
},
{
"local escape analysis (return pointer to int as out arg)",
func () interface{} {
x := GetX()
v = int8(*x)
return nil
},
},
{
"return &int(5)",
func () interface{} {
var x int = 5
return &x
},
},
{
"return &slice[0]",
func () interface{} {
return &prealloc[0]
},
},
{
"return &(xint8)slice[0]",
func () interface{} {
x := (xint8)(prealloc[0]) // can't take the address without a new variable
return &x
},
},
{
"return &array[0]",
func () interface{} {
return &arr[0]
},
},
{
"return &astruct.field",
func () interface{} {
return &a.A
},
},
{
// note: we can't get a pointer to the map key
"return &map[1]",
func () interface{} {
mapval := mmap[1] // illegal to do &mmap[1]
return &mapval
},
},
{
"call with closure",
func () interface{} {
return closureHandler(func(x int) interface{} {
v = int8(x)
return &v
})
},
},
{
"assign function var to method",
func () interface{} {
return closureHandler(func(x int) interface{} {
setIndex = intSettable(prealloc).set
return nil
})
},
},
}
w := &tabwriter.Writer{}
w.Init(os.Stdout, 0, 8, 0, '\t', 0)
for _, test := range tests {
allocs := testing.AllocsPerRun(10, func() { test.f() })
fmt.Fprintf(w, "%s:\t%d\n", test.name, int(allocs))
}
w.Flush()
}
type intSettable []int8
func (is intSettable) set(x int) {
is[0] = int8(x)
}
//go:noinline
func SetX(x *int) {
*x = 1
}
//go:noinline
func GetX() (x *int) {
y := 9
return &y
}
//go:noinline
func va(v ...int8) []int8 {
return v
}
//go:noinline
func closureHandler(z func (int) interface{}) interface{} {
return z(4)
}
var vals []interface{} = []interface{}{1, "x", 0.4}
var z int
func BenchmarkLoopOverTypes(b *testing.B) {
for i := 0; i < 10000000; i++ {
for range vals {
z += 4
}
}
}
func BenchmarkTypeSwitch(b *testing.B) {
for i := 0; i < 10000000; i++ {
for _, val := range vals {
switch val.(type){
case int:
z += 4
case string:
z += 6
case float64:
z += 12
}
}
}
}
var rtInt = reflect.TypeOf(int(1))
var rtStr = reflect.TypeOf("")
var rtFloat64 = reflect.TypeOf(float64(0))
func BenchmarkReflectTypeSwitch(b *testing.B) {
for i := 0; i < 10000000; i++ {
for _, val := range vals {
switch x := reflect.TypeOf(val); {
case x == rtInt:
z += 4
case x == rtStr:
z += 6
case x == rtFloat64:
z += 12
}
}
}
}
type X struct{a int}
//go:noinline
func (x *X) A(v int) (int){return v+x.a}
var xInst *X = &X{1}
type XIface interface{A(int)int}
var xIfaceInst XIface = xInst
func BenchmarkStructPtrFunctionCall(b *testing.B) {
v := 0
for i := 0; i < 100000000; i++ {
v = xInst.A(v)
}
z = v
}
func BenchmarkInterfaceFunctionCall(b *testing.B) {
v := 0
for i := 0; i < 100000000; i++ {
v = xIfaceInst.A(i)
}
z = v
}
//go:noinline
func a1(x int) int {
return x + 1
}
func BenchmarkSingleArgFunctionCall(b *testing.B) {
v := 0
for i := 0; i < 100000000; i++ {
v = a1(v)
}
z = v
}
//go:noinline
func a2(a, b, c, d, e, f, g int) int {
return a + 1
}
func BenchmarkMultiArgFunctionCall(b *testing.B) {
v := 0
for i := 0; i < 100000000; i++ {
v = a2(v, 1, 2, 3, 4, 5, 6)
}
z = v
}
type argStruct struct{
a, b, c, d, e, f, g int
}
//go:noinline
func a3(x argStruct) int {
return x.a + 1
}
func BenchmarkStructArgFunctionCall(b *testing.B) {
v := 0
for i := 0; i < 100000000; i++ {
v = a3(argStruct{v, 1, 2, 3, 4, 5, 6})
}
z = v
}
//go:noinline
func a4(x int) (a, b, c, d, e, f, g int) {
return x + 1, x + 2, x + 3, x + 4, x + 5, x + 6, x + 7
}
func BenchmarkMultiOutArgFunctionCall(b *testing.B) {
g := 0
for i := 0; i < 100000000; i++ {
_, _, _, _, _, _, g = a4(g)
}
z = g
}
//go:noinline
func a5(x int) (a argStruct) {
return argStruct{x + 1, x + 2, x + 3, x + 4, x + 5, x + 6, x + 7}
}
func BenchmarkStructOutArgFunctionCall(b *testing.B) {
s := argStruct{}
for i := 0; i < 100000000; i++ {
s = a5(s.g)
}
z = s.g
}
//go:noinline
func a6(x int) (interface{}) {
return x + 1
}
func BenchmarkReturnNumberThroughInterfaceFunctionCall(b *testing.B) {
s := 0
for i := 0; i < 100000000; i++ {
s = a6(s).(int)
}
z = s
}
func BenchmarkReuseIntInInterface(b *testing.B) {
var x interface{} = 0
for i := 0; i < 100000000; i++ {
x = x.(int) + 1
}
z = x.(int)
}
func BenchmarkSingleUseIntInInterface(b *testing.B) {
var x interface{} = 0
var q = 0
for i := 0; i < 100000000; i++ {
q = q + x.(int) + 1
}
x = q
z = x.(int)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment