1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
package timer
import (
"fmt"
"io"
"sort"
"time"
)
var (
clocks map[string]*clock
firstStart time.Time
)
func Start(key string) {
if clocks == nil {
clocks = make(map[string]*clock)
firstStart = time.Now()
}
if c, ok := clocks[key]; ok {
c.Start()
} else {
clocks[key] = new(clock)
// do not start, first run = warmup time
}
}
func Stop(key string) {
clocks[key].Stop()
}
type clock struct {
total time.Duration
started time.Time
invocations int
}
func (c *clock) Start() {
c.started = time.Now()
c.invocations++
}
func (c *clock) Stop() {
if (c.started == time.Time{}) {
return // not started
}
d := time.Since(c.started)
c.total += d
c.started = time.Time{}
}
// entry for sorted output by Print()
type entry struct {
name string
total time.Duration
invocations int
pct float32
}
func (e *entry) String() string {
perOp := time.Duration(0)
if int64(e.invocations) != 0 {
perOp = time.Duration(int64(e.total) / int64(e.invocations))
}
return fmt.Sprint(pad(e.name), pad(fmt.Sprint(e.invocations, "x")), perOp, "/op\t", e.pct, " %\t", e.total, " total")
}
func pad(s string) string {
if len(s) >= 20 {
return s
}
return s + " "[:20-len(s)]
}
type entries []entry
func (l entries) Len() int { return len(l) }
func (l entries) Less(i, j int) bool { return l[i].total > l[j].total }
func (l entries) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func Print(out io.Writer) {
if clocks == nil {
return
}
wallTime := time.Since(firstStart)
lines := make(entries, 0, len(clocks))
var accounted time.Duration
for k, v := range clocks {
pct := 100 * float32(int64(v.total)) / float32(int64(wallTime))
lines = append(lines, entry{k, v.total, v.invocations, pct})
accounted += v.total
}
unaccounted := wallTime - accounted
pct := 100 * float32(int64(unaccounted)) / float32(int64(wallTime))
lines = append(lines, entry{"NOT TIMED", unaccounted, 1, pct})
sort.Sort(lines)
for _, l := range lines {
fmt.Fprintln(out, &l)
}
}
|