84 lines
1.5 KiB
Go
84 lines
1.5 KiB
Go
|
// +build debug
|
||
|
|
||
|
package goparsify
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"runtime"
|
||
|
"sort"
|
||
|
"strings"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
var parsers []*DebugParser
|
||
|
|
||
|
type DebugParser struct {
|
||
|
Description string
|
||
|
Caller string
|
||
|
Next Parser
|
||
|
Time time.Duration
|
||
|
Calls int
|
||
|
}
|
||
|
|
||
|
func (dp *DebugParser) Parse(ps *State) *Node {
|
||
|
start := time.Now()
|
||
|
|
||
|
ret := dp.Next(ps)
|
||
|
|
||
|
dp.Time = dp.Time + time.Since(start)
|
||
|
dp.Calls++
|
||
|
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
func getPackageName(f *runtime.Func) string {
|
||
|
parts := strings.Split(f.Name(), ".")
|
||
|
pl := len(parts)
|
||
|
|
||
|
if parts[pl-2][0] == '(' {
|
||
|
return strings.Join(parts[0:pl-2], ".")
|
||
|
} else {
|
||
|
return strings.Join(parts[0:pl-1], ".")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func NewParser(description string, p Parser) Parser {
|
||
|
fpcs := make([]uintptr, 1)
|
||
|
caller := ""
|
||
|
|
||
|
for i := 1; i < 10; i++ {
|
||
|
n := runtime.Callers(i, fpcs)
|
||
|
|
||
|
if n != 0 {
|
||
|
frame := runtime.FuncForPC(fpcs[0] - 1)
|
||
|
pkg := getPackageName(frame)
|
||
|
|
||
|
if pkg != "github.com/vektah/goparsify" {
|
||
|
file, line := frame.FileLine(fpcs[0] - 1)
|
||
|
caller = fmt.Sprintf("%s:%d", file, line)
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dp := &DebugParser{
|
||
|
Description: description,
|
||
|
Next: p,
|
||
|
Caller: caller,
|
||
|
}
|
||
|
|
||
|
parsers = append(parsers, dp)
|
||
|
return dp.Parse
|
||
|
}
|
||
|
|
||
|
func DumpDebugStats() {
|
||
|
sort.Slice(parsers, func(i, j int) bool {
|
||
|
return parsers[i].Time >= parsers[j].Time
|
||
|
})
|
||
|
|
||
|
fmt.Println("Parser stats:")
|
||
|
for _, parser := range parsers {
|
||
|
fmt.Printf("%20s\t%10s\t%10d\tcalls\t%s\n", parser.Description, parser.Time.String(), parser.Calls, parser.Caller)
|
||
|
}
|
||
|
}
|