1
2
3
4
5 package starlark_test
6
7 import (
8 "bytes"
9 "fmt"
10 "io/ioutil"
11 "path/filepath"
12 "strings"
13 "testing"
14
15 "go.starlark.net/lib/json"
16 "go.starlark.net/starlark"
17 "go.starlark.net/starlarktest"
18 )
19
20 func BenchmarkStarlark(b *testing.B) {
21 defer setOptions("")
22
23 starlark.Universe["json"] = json.Module
24
25 testdata := starlarktest.DataFile("starlark", ".")
26 thread := new(starlark.Thread)
27 for _, file := range []string{
28 "testdata/benchmark.star",
29
30 } {
31
32 filename := filepath.Join(testdata, file)
33
34 src, err := ioutil.ReadFile(filename)
35 if err != nil {
36 b.Error(err)
37 continue
38 }
39 setOptions(string(src))
40
41
42 globals, err := starlark.ExecFile(thread, filename, src, nil)
43 if err != nil {
44 reportEvalError(b, err)
45 }
46
47
48 for _, name := range globals.Keys() {
49 value := globals[name]
50 if fn, ok := value.(*starlark.Function); ok && strings.HasPrefix(name, "bench_") {
51 b.Run(name, func(b *testing.B) {
52 _, err := starlark.Call(thread, fn, starlark.Tuple{benchmark{b}}, nil)
53 if err != nil {
54 reportEvalError(b, err)
55 }
56 })
57 }
58 }
59 }
60 }
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 type benchmark struct {
78 b *testing.B
79 }
80
81 func (benchmark) Freeze() {}
82 func (benchmark) Truth() starlark.Bool { return true }
83 func (benchmark) Type() string { return "benchmark" }
84 func (benchmark) String() string { return "<benchmark>" }
85 func (benchmark) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: benchmark") }
86 func (benchmark) AttrNames() []string { return []string{"n", "restart", "start", "stop"} }
87 func (b benchmark) Attr(name string) (starlark.Value, error) {
88 switch name {
89 case "n":
90 return starlark.MakeInt(b.b.N), nil
91 case "restart":
92 return benchmarkRestart.BindReceiver(b), nil
93 case "start":
94 return benchmarkStart.BindReceiver(b), nil
95 case "stop":
96 return benchmarkStop.BindReceiver(b), nil
97 }
98 return nil, nil
99 }
100
101 var (
102 benchmarkRestart = starlark.NewBuiltin("restart", benchmarkRestartImpl)
103 benchmarkStart = starlark.NewBuiltin("start", benchmarkStartImpl)
104 benchmarkStop = starlark.NewBuiltin("stop", benchmarkStopImpl)
105 )
106
107 func benchmarkRestartImpl(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
108 b.Receiver().(benchmark).b.ResetTimer()
109 return starlark.None, nil
110 }
111
112 func benchmarkStartImpl(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
113 b.Receiver().(benchmark).b.StartTimer()
114 return starlark.None, nil
115 }
116
117 func benchmarkStopImpl(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
118 b.Receiver().(benchmark).b.StopTimer()
119 return starlark.None, nil
120 }
121
122
123
124 func BenchmarkProgram(b *testing.B) {
125
126 filename := starlarktest.DataFile("starlark", "testdata/paths.star")
127 var src []byte
128 b.Run("read", func(b *testing.B) {
129 for i := 0; i < b.N; i++ {
130 var err error
131 src, err = ioutil.ReadFile(filename)
132 if err != nil {
133 b.Fatal(err)
134 }
135 }
136 })
137
138
139 var prog *starlark.Program
140 b.Run("compile", func(b *testing.B) {
141 for i := 0; i < b.N; i++ {
142 var err error
143 _, prog, err = starlark.SourceProgram(filename, src, starlark.StringDict(nil).Has)
144 if err != nil {
145 b.Fatal(err)
146 }
147 }
148 })
149
150
151
152 var out bytes.Buffer
153 b.Run("encode", func(b *testing.B) {
154 for i := 0; i < b.N; i++ {
155 out.Reset()
156 if err := prog.Write(&out); err != nil {
157 b.Fatal(err)
158 }
159 }
160 })
161
162
163
164 b.Run("decode", func(b *testing.B) {
165 for i := 0; i < b.N; i++ {
166 in := bytes.NewReader(out.Bytes())
167 if _, err := starlark.CompiledProgram(in); err != nil {
168 b.Fatal(err)
169 }
170 }
171 })
172 }
173
View as plain text