status-go/vendor/github.com/anacrolix/missinggo/perf/timer.go

105 lines
1.5 KiB
Go

package perf
import (
"log"
"runtime"
"time"
)
type Timer struct {
started time.Time
log bool
name string
marked bool
}
func NewTimer(opts ...timerOpt) (t *Timer) {
t = &Timer{
started: time.Now(),
}
for _, o := range opts {
o(t)
}
if t.log && t.name != "" {
log.Printf("starting timer %q", t.name)
}
runtime.SetFinalizer(t, func(t *Timer) {
if t.marked {
return
}
log.Printf("timer %#v was never marked", t)
})
return
}
type timerOpt func(*Timer)
func Log(t *Timer) {
t.log = true
}
func Name(name string) func(*Timer) {
return func(t *Timer) {
t.name = name
}
}
func (t *Timer) Mark(events ...string) time.Duration {
d := time.Since(t.started)
if len(events) == 0 {
if t.name == "" {
panic("no name or events specified")
}
t.addDuration(t.name, d)
} else {
for _, e := range events {
if t.name != "" {
e = t.name + "/" + e
}
t.addDuration(e, d)
}
}
return d
}
func (t *Timer) MarkOk(ok bool) {
if ok {
t.Mark("ok")
} else {
t.Mark("not ok")
}
}
func (t *Timer) MarkErr(err error) {
if err == nil {
t.Mark("success")
} else {
t.Mark("error")
}
}
func (t *Timer) addDuration(desc string, d time.Duration) {
t.marked = true
mu.RLock()
e := events[desc]
mu.RUnlock()
if e == nil {
mu.Lock()
e = events[desc]
if e == nil {
e = new(Event)
e.Init()
events[desc] = e
}
mu.Unlock()
}
e.Add(d)
if t.log {
if t.name != "" {
log.Printf("timer %q got event %q after %s", t.name, desc, d)
} else {
log.Printf("marking event %q after %s", desc, d)
}
}
}