Commit 4e36b859 authored by Brian Atkinson's avatar Brian Atkinson Committed by Dylan Trotter

Add a bunch of micro benchmarks. (#201)

Method covered by new benchmarks:
* Dict.GetItem
* Dict.IterItems
* Dict.IterKeys
* Dict.IterValues
* NewInt - Fixed so that references aren't elided anymore.
* NewStr
parent 7ddfe607
......@@ -17,6 +17,7 @@ package grumpy
import (
"reflect"
"regexp"
"runtime"
"sync"
"testing"
"time"
......@@ -244,6 +245,146 @@ func TestDictGetItem(t *testing.T) {
}
}
// BenchmarkDictGetItem is to keep an eye on the speed of contended dict access
// in a fast read loop.
func BenchmarkDictGetItem(b *testing.B) {
d := newTestDict(
"foo", 1,
"bar", 2,
None, 3,
4, 5)
k := NewInt(4).ToObject()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
f := NewRootFrame()
var ret *Object
var raised *BaseException
for pb.Next() {
ret, raised = d.GetItem(f, k)
}
runtime.KeepAlive(ret)
runtime.KeepAlive(raised)
})
}
func BenchmarkDictIterItems(b *testing.B) {
bench := func(d *Dict) func(*testing.B) {
return func(b *testing.B) {
f := NewRootFrame()
args := f.MakeArgs(1)
args[0] = d.ToObject()
b.ResetTimer()
var ret *Object
var raised *BaseException
for i := 0; i < b.N; i++ {
iter, _ := dictIterItems(f, args, nil)
for {
ret, raised = Next(f, iter)
if raised != nil {
if !raised.isInstance(StopIterationType) {
b.Fatalf("iteration failed with: %v", raised)
}
f.RestoreExc(nil, nil)
break
}
}
}
runtime.KeepAlive(ret)
runtime.KeepAlive(raised)
}
}
b.Run("0-elements", bench(newTestDict()))
b.Run("1-elements", bench(newTestDict(1, 2)))
b.Run("2-elements", bench(newTestDict(1, 2, 3, 4)))
b.Run("3-elements", bench(newTestDict(1, 2, 3, 4, 5, 6)))
b.Run("4-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8)))
b.Run("5-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
b.Run("6-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)))
b.Run("7-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)))
b.Run("8-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)))
}
func BenchmarkDictIterKeys(b *testing.B) {
bench := func(d *Dict) func(*testing.B) {
return func(b *testing.B) {
f := NewRootFrame()
args := f.MakeArgs(1)
args[0] = d.ToObject()
b.ResetTimer()
var ret *Object
var raised *BaseException
for i := 0; i < b.N; i++ {
iter, _ := dictIterKeys(f, args, nil)
for {
ret, raised = Next(f, iter)
if raised != nil {
if !raised.isInstance(StopIterationType) {
b.Fatalf("iteration failed with: %v", raised)
}
f.RestoreExc(nil, nil)
break
}
}
}
runtime.KeepAlive(ret)
runtime.KeepAlive(raised)
}
}
b.Run("0-elements", bench(newTestDict()))
b.Run("1-elements", bench(newTestDict(1, 2)))
b.Run("2-elements", bench(newTestDict(1, 2, 3, 4)))
b.Run("3-elements", bench(newTestDict(1, 2, 3, 4, 5, 6)))
b.Run("4-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8)))
b.Run("5-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
b.Run("6-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)))
b.Run("7-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)))
b.Run("8-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)))
}
func BenchmarkDictIterValues(b *testing.B) {
bench := func(d *Dict) func(*testing.B) {
return func(b *testing.B) {
f := NewRootFrame()
args := f.MakeArgs(1)
args[0] = d.ToObject()
b.ResetTimer()
var ret *Object
var raised *BaseException
for i := 0; i < b.N; i++ {
iter, _ := dictIterValues(f, args, nil)
for {
ret, raised = Next(f, iter)
if raised != nil {
if !raised.isInstance(StopIterationType) {
b.Fatalf("iteration failed with: %v", raised)
}
f.RestoreExc(nil, nil)
break
}
}
}
runtime.KeepAlive(ret)
runtime.KeepAlive(raised)
}
}
b.Run("0-elements", bench(newTestDict()))
b.Run("1-elements", bench(newTestDict(1, 2)))
b.Run("2-elements", bench(newTestDict(1, 2, 3, 4)))
b.Run("3-elements", bench(newTestDict(1, 2, 3, 4, 5, 6)))
b.Run("4-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8)))
b.Run("5-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
b.Run("6-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)))
b.Run("7-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)))
b.Run("8-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)))
}
func TestDictGetItemString(t *testing.T) {
getItemString := newBuiltinFunction("TestDictGetItemString", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
if raised := checkFunctionArgs(f, "TestDictGetItem", args, DictType, StrType); raised != nil {
......
......@@ -16,6 +16,7 @@ package grumpy
import (
"math/big"
"runtime"
"testing"
)
......@@ -202,15 +203,19 @@ func TestIntNewInterned(t *testing.T) {
func BenchmarkIntNew(b *testing.B) {
b.Run("interned", func(b *testing.B) {
var ret *Object
for i := 0; i < b.N; i++ {
_ = NewInt(1).ToObject()
ret = NewInt(1).ToObject()
}
runtime.KeepAlive(ret)
})
b.Run("not interned", func(b *testing.B) {
var ret *Object
for i := 0; i < b.N; i++ {
_ = NewInt(internedIntMax + 5).ToObject()
ret = NewInt(internedIntMax + 5).ToObject()
}
runtime.KeepAlive(ret)
})
}
......
......@@ -18,6 +18,7 @@ import (
"fmt"
"math/big"
"reflect"
"runtime"
"testing"
)
......@@ -29,6 +30,14 @@ func TestNewStr(t *testing.T) {
}
}
func BenchmarkNewStr(b *testing.B) {
var ret *Str
for i := 0; i < b.N; i++ {
ret = NewStr("foo")
}
runtime.KeepAlive(ret)
}
// # On a 64bit system:
// >>> hash("foo")
// -4177197833195190597
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment