Skip to content

Commit adb139a

Browse files
authored
Add spans
1 parent 7795708 commit adb139a

File tree

6 files changed

+63
-0
lines changed

6 files changed

+63
-0
lines changed

compiler/compiler.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ func Compile(tree *parser.Tree, config *conf.Config) (program *Program, err erro
5050
}
5151
}
5252

53+
var span *Span
54+
if len(c.spans) > 0 {
55+
span = c.spans[0]
56+
}
57+
5358
program = NewProgram(
5459
tree.Source,
5560
tree.Node,
@@ -60,6 +65,7 @@ func Compile(tree *parser.Tree, config *conf.Config) (program *Program, err erro
6065
c.arguments,
6166
c.functions,
6267
c.debugInfo,
68+
span,
6369
)
6470
return
6571
}
@@ -76,6 +82,7 @@ type compiler struct {
7682
functionsIndex map[string]int
7783
debugInfo map[string]string
7884
nodes []ast.Node
85+
spans []*Span
7986
chains [][]int
8087
arguments []int
8188
}
@@ -193,6 +200,28 @@ func (c *compiler) compile(node ast.Node) {
193200
c.nodes = c.nodes[:len(c.nodes)-1]
194201
}()
195202

203+
if c.config != nil && c.config.Profile {
204+
span := &Span{
205+
Name: reflect.TypeOf(node).String(),
206+
Expression: node.String(),
207+
}
208+
if len(c.spans) > 0 {
209+
prev := c.spans[len(c.spans)-1]
210+
prev.Children = append(prev.Children, span)
211+
}
212+
c.spans = append(c.spans, span)
213+
defer func() {
214+
if len(c.spans) > 1 {
215+
c.spans = c.spans[:len(c.spans)-1]
216+
}
217+
}()
218+
219+
c.emit(OpProfileStart, c.addConstant(span))
220+
defer func() {
221+
c.emit(OpProfileEnd, c.addConstant(span))
222+
}()
223+
}
224+
196225
switch n := node.(type) {
197226
case *ast.NilNode:
198227
c.NilNode(n)

conf/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type Config struct {
2020
ExpectAny bool
2121
Optimize bool
2222
Strict bool
23+
Profile bool
2324
ConstFns map[string]reflect.Value
2425
Visitors []ast.Visitor
2526
Functions FunctionsTable

vm/opcodes.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ const (
8181
OpGroupBy
8282
OpSortBy
8383
OpSort
84+
OpProfileStart
85+
OpProfileEnd
8486
OpBegin
8587
OpEnd // This opcode must be at the end of this list.
8688
)

vm/program.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type Program struct {
2727
variables int
2828
functions []Function
2929
debugInfo map[string]string
30+
span *Span
3031
}
3132

3233
// NewProgram returns a new Program. It's used by the compiler.
@@ -40,6 +41,7 @@ func NewProgram(
4041
arguments []int,
4142
functions []Function,
4243
debugInfo map[string]string,
44+
span *Span,
4345
) *Program {
4446
return &Program{
4547
source: source,
@@ -51,6 +53,7 @@ func NewProgram(
5153
Arguments: arguments,
5254
functions: functions,
5355
debugInfo: debugInfo,
56+
span: span,
5457
}
5558
}
5659

@@ -360,6 +363,12 @@ func (program *Program) DisassembleWriter(w io.Writer) {
360363
case OpSort:
361364
code("OpSort")
362365

366+
case OpProfileStart:
367+
code("OpProfileStart")
368+
369+
case OpProfileEnd:
370+
code("OpProfileEnd")
371+
363372
case OpBegin:
364373
code("OpBegin")
365374

vm/utils.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package vm
22

33
import (
44
"reflect"
5+
"time"
56
)
67

78
type (
@@ -25,3 +26,15 @@ type Scope struct {
2526
}
2627

2728
type groupBy = map[any][]any
29+
30+
type Span struct {
31+
Name string `json:"name"`
32+
Expression string `json:"expression"`
33+
Duration int64 `json:"duration"`
34+
Children []*Span `json:"children"`
35+
start time.Time
36+
}
37+
38+
func GetSpan(program *Program) *Span {
39+
return program.span
40+
}

vm/vm.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"regexp"
99
"sort"
1010
"strings"
11+
"time"
1112

1213
"github.com/expr-lang/expr/builtin"
1314
"github.com/expr-lang/expr/file"
@@ -523,6 +524,14 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
523524
vm.memGrow(uint(scope.Len))
524525
vm.push(sortable.Array)
525526

527+
case OpProfileStart:
528+
span := program.Constants[arg].(*Span)
529+
span.start = time.Now()
530+
531+
case OpProfileEnd:
532+
span := program.Constants[arg].(*Span)
533+
span.Duration += time.Since(span.start).Nanoseconds()
534+
526535
case OpBegin:
527536
a := vm.pop()
528537
array := reflect.ValueOf(a)

0 commit comments

Comments
 (0)