Skip to content

Commit 4cddc26

Browse files
Rudimentary stack profiler
Usage: JSONNET_STACK_PROFILE=stacks.out jsonnet main.jsonnet cat stacks.out | flamegraph.pl --hash > flamegraph.svg
1 parent 74b3a1b commit 4cddc26

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

Diff for: cmd/jsonnet/cmd.go

+3
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ func main() {
397397
cmd.StartCPUProfile()
398398
defer cmd.StopCPUProfile()
399399

400+
jsonnet.StartStackProfile()
401+
defer jsonnet.StopStackProfile()
402+
400403
vm := jsonnet.MakeVM()
401404
vm.ErrorFormatter.SetColorFormatter(color.New(color.FgRed).Fprintf)
402405

Diff for: interpreter.go

+43
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,18 @@ limitations under the License.
1717
package jsonnet
1818

1919
import (
20+
"bufio"
2021
"bytes"
2122
"fmt"
2223
"io"
24+
"log"
2325
"math"
26+
"math/rand"
27+
"os"
2428
"reflect"
2529
"sort"
2630
"strconv"
31+
"strings"
2732

2833
"github.com/google/go-jsonnet/ast"
2934
"github.com/google/go-jsonnet/astgen"
@@ -968,7 +973,45 @@ func jsonToValue(i *interpreter, v interface{}) (value, error) {
968973
}
969974
}
970975

976+
var (
977+
stackProfileOut *bufio.Writer
978+
stackProfileRatio = 0.01
979+
)
980+
981+
func StartStackProfile() {
982+
var err error
983+
984+
if os.Getenv("JSONNET_STACK_PROFILE") != "" {
985+
stackProfileOutFile, err := os.Create(os.Getenv("JSONNET_STACK_PROFILE"))
986+
if err != nil {
987+
log.Fatal("could not create stack profile: ", err)
988+
}
989+
stackProfileOut = bufio.NewWriter(stackProfileOutFile)
990+
}
991+
992+
if os.Getenv("JSONNET_STACK_PROFILE_RATIO") != "" {
993+
stackProfileRatio, err = strconv.ParseFloat(os.Getenv("JSONNET_STACK_PROFILE_RATIO"), 64)
994+
if err != nil {
995+
log.Fatal("could not parse stack profile ratio: ", err)
996+
}
997+
}
998+
}
999+
1000+
func StopStackProfile() {
1001+
if stackProfileOut != nil {
1002+
stackProfileOut.Flush()
1003+
}
1004+
}
1005+
9711006
func (i *interpreter) EvalInCleanEnv(env *environment, ast ast.Node, trimmable bool) (value, error) {
1007+
if stackProfileOut != nil && rand.Float64() < stackProfileRatio {
1008+
stack := []string{}
1009+
for _, frame := range i.getCurrentStackTrace() {
1010+
stack = append(stack, frame.Loc.String()+":"+frame.Name)
1011+
}
1012+
fmt.Fprintln(stackProfileOut, strings.Join(stack, ";")+" 1")
1013+
}
1014+
9721015
err := i.newCall(*env, trimmable)
9731016
if err != nil {
9741017
return nil, err

0 commit comments

Comments
 (0)