Skip to content

Commit 95617b7

Browse files
ncwcorona10
authored andcommitted
Implement benchmark framework for gpython along with a couple of benchmarks (#51)
This reworks the existing test framework so it can be used for benchmarks too. Note that it now uses the subtest framework which makes the test output much neater. To run the benchmarks use cd vm go test -v -run XXX -bench . Fixes #50
1 parent 9985b49 commit 95617b7

File tree

4 files changed

+75
-16
lines changed

4 files changed

+75
-16
lines changed

pytest/pytest.go

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import (
1818
"github.com/go-python/gpython/vm"
1919
)
2020

21-
// Run the code in str
22-
func Run(t *testing.T, prog string) {
21+
// Compile the program in the file prog to code in the module that is returned
22+
func compileProgram(t testing.TB, prog string) (*py.Module, *py.Code) {
2323
f, err := os.Open(prog)
2424
if err != nil {
2525
t.Fatalf("%s: Open failed: %v", prog, err)
@@ -43,55 +43,80 @@ func Run(t *testing.T, prog string) {
4343
code := obj.(*py.Code)
4444
module := py.NewModule("__main__", "", nil, nil)
4545
module.Globals["__file__"] = py.String(prog)
46+
return module, code
47+
}
4648

47-
_, err = vm.Run(module.Globals, module.Globals, code, nil)
49+
// Run the code in the module
50+
func run(t testing.TB, module *py.Module, code *py.Code) {
51+
_, err := vm.Run(module.Globals, module.Globals, code, nil)
4852
if err != nil {
4953
if wantErr, ok := module.Globals["err"]; ok {
5054
wantErrObj, ok := wantErr.(py.Object)
5155
if !ok {
52-
t.Fatalf("%s: want err is not py.Object: %#v", prog, wantErr)
56+
t.Fatalf("want err is not py.Object: %#v", wantErr)
5357
}
5458
gotExc, ok := err.(py.ExceptionInfo)
5559
if !ok {
56-
t.Fatalf("%s: got err is not ExceptionInfo: %#v", prog, err)
60+
t.Fatalf("got err is not ExceptionInfo: %#v", err)
5761
}
5862
if gotExc.Value.Type() != wantErrObj.Type() {
59-
t.Fatalf("%s: Want exception %v got %v", prog, wantErrObj, gotExc.Value)
63+
t.Fatalf("Want exception %v got %v", wantErrObj, gotExc.Value)
6064
}
61-
t.Logf("%s: matched exception", prog)
65+
// t.Logf("matched exception")
6266
return
6367
} else {
6468
py.TracebackDump(err)
65-
t.Fatalf("%s: Run failed: %v at %q", prog, err, module.Globals["doc"])
69+
t.Fatalf("Run failed: %v at %q", err, module.Globals["doc"])
6670
}
6771
}
6872

6973
// t.Logf("%s: Return = %v", prog, res)
7074
if doc, ok := module.Globals["doc"]; ok {
7175
if docStr, ok := doc.(py.String); ok {
7276
if string(docStr) != "finished" {
73-
t.Fatalf("%s: Didn't finish at %q", prog, docStr)
77+
t.Fatalf("Didn't finish at %q", docStr)
7478
}
7579
} else {
76-
t.Fatalf("%s: Set doc variable to non string: %#v", prog, doc)
80+
t.Fatalf("Set doc variable to non string: %#v", doc)
7781
}
7882
} else {
79-
t.Fatalf("%s: Didn't set doc variable at all", prog)
83+
t.Fatalf("Didn't set doc variable at all")
8084
}
8185
}
8286

83-
// Runs the tests in the directory passed in
84-
func RunTests(t *testing.T, testDir string) {
87+
// find the python files in the directory passed in
88+
func findFiles(t testing.TB, testDir string) (names []string) {
8589
files, err := ioutil.ReadDir(testDir)
8690
if err != nil {
8791
t.Fatalf("ReadDir failed: %v", err)
8892
}
8993
for _, f := range files {
9094
name := f.Name()
9195
if !strings.HasPrefix(name, "lib") && strings.HasSuffix(name, ".py") {
92-
name := path.Join(testDir, name)
93-
t.Logf("%s: Running", name)
94-
Run(t, name)
96+
names = append(names, name)
9597
}
9698
}
99+
return names
100+
}
101+
102+
// RunTests runs the tests in the directory passed in
103+
func RunTests(t *testing.T, testDir string) {
104+
for _, name := range findFiles(t, testDir) {
105+
t.Run(name, func(t *testing.T) {
106+
module, code := compileProgram(t, path.Join(testDir, name))
107+
run(t, module, code)
108+
})
109+
}
110+
}
111+
112+
// RunBenchmarks runs the benchmarks in the directory passed in
113+
func RunBenchmarks(b *testing.B, testDir string) {
114+
for _, name := range findFiles(b, testDir) {
115+
module, code := compileProgram(b, path.Join(testDir, name))
116+
b.Run(name, func(b *testing.B) {
117+
for i := 0; i < b.N; i++ {
118+
run(b, module, code)
119+
}
120+
})
121+
}
97122
}

vm/benchmarks/fib.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2019 The go-python Authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style
3+
# license that can be found in the LICENSE file.
4+
5+
# Benchmark adapted from https://github.com/d5/tengobench/
6+
doc="fib recursion test"
7+
def fib(n):
8+
if n == 0:
9+
return 0
10+
elif n == 1:
11+
return 1
12+
return fib(n - 2) + fib(n - 1)
13+
14+
fib(25)
15+
doc="finished"

vm/benchmarks/fibtc.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2019 The go-python Authors. All rights reserved.
2+
# Use of this source code is governed by a BSD-style
3+
# license that can be found in the LICENSE file.
4+
5+
# Benchmark adapted from https://github.com/d5/tengobench/
6+
doc="fib tail call recursion test"
7+
def fib(n, a, b):
8+
if n == 0:
9+
return a
10+
elif n == 1:
11+
return b
12+
return fib(n-1, b, a+b)
13+
14+
fib(35, 0, 1)
15+
doc="finished"

vm/vm_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ import (
1313
func TestVm(t *testing.T) {
1414
pytest.RunTests(t, "tests")
1515
}
16+
17+
func BenchmarkVM(b *testing.B) {
18+
pytest.RunBenchmarks(b, "benchmarks")
19+
}

0 commit comments

Comments
 (0)