Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit 4e36b85

Browse files
nairb774trotterdylan
authored andcommitted
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
1 parent 7ddfe60 commit 4e36b85

3 files changed

Lines changed: 157 additions & 2 deletions

File tree

runtime/dict_test.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package grumpy
1717
import (
1818
"reflect"
1919
"regexp"
20+
"runtime"
2021
"sync"
2122
"testing"
2223
"time"
@@ -244,6 +245,146 @@ func TestDictGetItem(t *testing.T) {
244245
}
245246
}
246247

248+
// BenchmarkDictGetItem is to keep an eye on the speed of contended dict access
249+
// in a fast read loop.
250+
func BenchmarkDictGetItem(b *testing.B) {
251+
d := newTestDict(
252+
"foo", 1,
253+
"bar", 2,
254+
None, 3,
255+
4, 5)
256+
k := NewInt(4).ToObject()
257+
258+
b.ResetTimer()
259+
b.RunParallel(func(pb *testing.PB) {
260+
f := NewRootFrame()
261+
var ret *Object
262+
var raised *BaseException
263+
for pb.Next() {
264+
ret, raised = d.GetItem(f, k)
265+
}
266+
runtime.KeepAlive(ret)
267+
runtime.KeepAlive(raised)
268+
})
269+
}
270+
271+
func BenchmarkDictIterItems(b *testing.B) {
272+
bench := func(d *Dict) func(*testing.B) {
273+
return func(b *testing.B) {
274+
f := NewRootFrame()
275+
args := f.MakeArgs(1)
276+
args[0] = d.ToObject()
277+
b.ResetTimer()
278+
279+
var ret *Object
280+
var raised *BaseException
281+
for i := 0; i < b.N; i++ {
282+
iter, _ := dictIterItems(f, args, nil)
283+
for {
284+
ret, raised = Next(f, iter)
285+
if raised != nil {
286+
if !raised.isInstance(StopIterationType) {
287+
b.Fatalf("iteration failed with: %v", raised)
288+
}
289+
f.RestoreExc(nil, nil)
290+
break
291+
}
292+
}
293+
}
294+
runtime.KeepAlive(ret)
295+
runtime.KeepAlive(raised)
296+
}
297+
}
298+
299+
b.Run("0-elements", bench(newTestDict()))
300+
b.Run("1-elements", bench(newTestDict(1, 2)))
301+
b.Run("2-elements", bench(newTestDict(1, 2, 3, 4)))
302+
b.Run("3-elements", bench(newTestDict(1, 2, 3, 4, 5, 6)))
303+
b.Run("4-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8)))
304+
b.Run("5-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
305+
b.Run("6-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)))
306+
b.Run("7-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)))
307+
b.Run("8-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)))
308+
}
309+
310+
func BenchmarkDictIterKeys(b *testing.B) {
311+
bench := func(d *Dict) func(*testing.B) {
312+
return func(b *testing.B) {
313+
f := NewRootFrame()
314+
args := f.MakeArgs(1)
315+
args[0] = d.ToObject()
316+
b.ResetTimer()
317+
318+
var ret *Object
319+
var raised *BaseException
320+
for i := 0; i < b.N; i++ {
321+
iter, _ := dictIterKeys(f, args, nil)
322+
for {
323+
ret, raised = Next(f, iter)
324+
if raised != nil {
325+
if !raised.isInstance(StopIterationType) {
326+
b.Fatalf("iteration failed with: %v", raised)
327+
}
328+
f.RestoreExc(nil, nil)
329+
break
330+
}
331+
}
332+
}
333+
runtime.KeepAlive(ret)
334+
runtime.KeepAlive(raised)
335+
}
336+
}
337+
338+
b.Run("0-elements", bench(newTestDict()))
339+
b.Run("1-elements", bench(newTestDict(1, 2)))
340+
b.Run("2-elements", bench(newTestDict(1, 2, 3, 4)))
341+
b.Run("3-elements", bench(newTestDict(1, 2, 3, 4, 5, 6)))
342+
b.Run("4-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8)))
343+
b.Run("5-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
344+
b.Run("6-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)))
345+
b.Run("7-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)))
346+
b.Run("8-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)))
347+
}
348+
349+
func BenchmarkDictIterValues(b *testing.B) {
350+
bench := func(d *Dict) func(*testing.B) {
351+
return func(b *testing.B) {
352+
f := NewRootFrame()
353+
args := f.MakeArgs(1)
354+
args[0] = d.ToObject()
355+
b.ResetTimer()
356+
357+
var ret *Object
358+
var raised *BaseException
359+
for i := 0; i < b.N; i++ {
360+
iter, _ := dictIterValues(f, args, nil)
361+
for {
362+
ret, raised = Next(f, iter)
363+
if raised != nil {
364+
if !raised.isInstance(StopIterationType) {
365+
b.Fatalf("iteration failed with: %v", raised)
366+
}
367+
f.RestoreExc(nil, nil)
368+
break
369+
}
370+
}
371+
}
372+
runtime.KeepAlive(ret)
373+
runtime.KeepAlive(raised)
374+
}
375+
}
376+
377+
b.Run("0-elements", bench(newTestDict()))
378+
b.Run("1-elements", bench(newTestDict(1, 2)))
379+
b.Run("2-elements", bench(newTestDict(1, 2, 3, 4)))
380+
b.Run("3-elements", bench(newTestDict(1, 2, 3, 4, 5, 6)))
381+
b.Run("4-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8)))
382+
b.Run("5-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
383+
b.Run("6-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)))
384+
b.Run("7-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)))
385+
b.Run("8-elements", bench(newTestDict(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)))
386+
}
387+
247388
func TestDictGetItemString(t *testing.T) {
248389
getItemString := newBuiltinFunction("TestDictGetItemString", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
249390
if raised := checkFunctionArgs(f, "TestDictGetItem", args, DictType, StrType); raised != nil {

runtime/int_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package grumpy
1616

1717
import (
1818
"math/big"
19+
"runtime"
1920
"testing"
2021
)
2122

@@ -202,15 +203,19 @@ func TestIntNewInterned(t *testing.T) {
202203

203204
func BenchmarkIntNew(b *testing.B) {
204205
b.Run("interned", func(b *testing.B) {
206+
var ret *Object
205207
for i := 0; i < b.N; i++ {
206-
_ = NewInt(1).ToObject()
208+
ret = NewInt(1).ToObject()
207209
}
210+
runtime.KeepAlive(ret)
208211
})
209212

210213
b.Run("not interned", func(b *testing.B) {
214+
var ret *Object
211215
for i := 0; i < b.N; i++ {
212-
_ = NewInt(internedIntMax + 5).ToObject()
216+
ret = NewInt(internedIntMax + 5).ToObject()
213217
}
218+
runtime.KeepAlive(ret)
214219
})
215220
}
216221

runtime/str_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"fmt"
1919
"math/big"
2020
"reflect"
21+
"runtime"
2122
"testing"
2223
)
2324

@@ -29,6 +30,14 @@ func TestNewStr(t *testing.T) {
2930
}
3031
}
3132

33+
func BenchmarkNewStr(b *testing.B) {
34+
var ret *Str
35+
for i := 0; i < b.N; i++ {
36+
ret = NewStr("foo")
37+
}
38+
runtime.KeepAlive(ret)
39+
}
40+
3241
// # On a 64bit system:
3342
// >>> hash("foo")
3443
// -4177197833195190597

0 commit comments

Comments
 (0)