github.com/searKing/golang/go@v1.2.117/time/cost.go (about) 1 package time 2 3 import ( 4 "fmt" 5 "io" 6 "sort" 7 "strings" 8 "time" 9 10 runtime_ "github.com/searKing/golang/go/runtime" 11 ) 12 13 type Cost struct { 14 start time.Time 15 } 16 17 func (c *Cost) Start() { 18 c.start = time.Now() 19 } 20 21 func (c *Cost) Elapse() time.Duration { 22 return time.Now().Sub(c.start) 23 } 24 25 func (c *Cost) ElapseFunc(f func(d time.Duration)) { 26 if f != nil { 27 f(c.Elapse()) 28 } 29 } 30 31 type CostTick struct { 32 points []time.Time 33 messages []string 34 costs []time.Duration 35 // Lesser reports whether the element with duration i 36 // must sort before the element with duration j. 37 // sorting in decreasing order of cost if Lesser is nil 38 // behaves like Less in sort.Interface 39 Lesser func(i time.Duration, j time.Duration) bool 40 } 41 42 func (c *CostTick) Reset() { 43 c.points = nil 44 c.messages = nil 45 c.costs = nil 46 } 47 48 func (c *CostTick) Tick(msg string) { 49 if msg == "" { 50 caller, file, line := runtime_.GetShortCallerFuncFileLine(1) 51 msg = fmt.Sprintf("%s() %s:%d", caller, file, line) 52 } 53 c.points = append(c.points, time.Now()) 54 c.messages = append(c.messages, msg) 55 if len(c.costs) == 0 || len(c.points) == 1 { 56 c.costs = append(c.costs, 0) 57 } else { 58 c.costs = append(c.costs, c.points[len(c.points)-1].Sub(c.points[len(c.points)-2])) 59 } 60 } 61 62 func (c CostTick) String() string { 63 var buf strings.Builder 64 var scanned bool 65 c.Walk(func(idx int, msg string, cost time.Duration, at time.Time) (next bool) { 66 if scanned { 67 buf.WriteString("\n") 68 } 69 buf.WriteString(fmt.Sprintf("#%d, msg: %s, cost %s, at %s", idx, msg, cost, at)) 70 scanned = true 71 return true 72 }) 73 return buf.String() 74 } 75 76 func (c CostTick) Format(s fmt.State, verb rune) { 77 switch verb { 78 case 'v': 79 if s.Flag('+') { 80 _, _ = io.WriteString(s, c.String()) 81 } 82 fallthrough 83 case 's', 'q': 84 var costs []string 85 c.Walk(func(idx int, msg string, cost time.Duration, at time.Time) (next bool) { 86 costs = append(costs, fmt.Sprintf("%s(%s)", msg, cost)) 87 return true 88 }) 89 _, _ = fmt.Fprintf(s, "%v", costs) 90 } 91 } 92 93 func (c CostTick) Costs() []time.Duration { 94 var costs []time.Duration 95 c.Walk(func(idx int, msg string, cost time.Duration, at time.Time) (next bool) { 96 costs = append(costs, cost) 97 return true 98 }) 99 return costs 100 } 101 102 // Walk iterate costs 103 // Walk stop if f(...) returns false. 104 func (c CostTick) Walk(f func(idx int, msg string, cost time.Duration, at time.Time) (next bool)) { 105 if f == nil { 106 return 107 } 108 109 for i, p := range c.points { 110 if f(i, c.messages[i], c.costs[i], p) { 111 continue 112 } 113 return 114 } 115 } 116 117 // sorting in decreasing order of cost. 118 func (c CostTick) Len() int { return len(c.points) } 119 120 func (c CostTick) Less(i, j int) bool { 121 if c.Lesser != nil { 122 return c.Lesser(c.costs[i], c.costs[j]) 123 } 124 return c.costs[i] > c.costs[j] 125 } 126 127 func (c *CostTick) Swap(i, j int) { 128 c.points[i], c.points[j] = c.points[j], c.points[i] 129 c.messages[i], c.messages[j] = c.messages[j], c.messages[i] 130 c.costs[i], c.costs[j] = c.costs[j], c.costs[i] 131 } 132 133 // Sort is a convenience method: x.Sort() calls Sort(x). 134 func (c *CostTick) Sort() { sort.Sort(c) }