timer.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package perf
  2. import (
  3. "log"
  4. "runtime"
  5. "time"
  6. )
  7. type Timer struct {
  8. started time.Time
  9. log bool
  10. name string
  11. marked bool
  12. }
  13. func NewTimer(opts ...timerOpt) (t *Timer) {
  14. t = &Timer{
  15. started: time.Now(),
  16. }
  17. for _, o := range opts {
  18. o(t)
  19. }
  20. if t.log && t.name != "" {
  21. log.Printf("starting timer %q", t.name)
  22. }
  23. runtime.SetFinalizer(t, func(t *Timer) {
  24. if t.marked {
  25. return
  26. }
  27. log.Printf("timer %#v was never marked", t)
  28. })
  29. return
  30. }
  31. type timerOpt func(*Timer)
  32. func Log(t *Timer) {
  33. t.log = true
  34. }
  35. func Name(name string) func(*Timer) {
  36. return func(t *Timer) {
  37. t.name = name
  38. }
  39. }
  40. func (t *Timer) Mark(events ...string) time.Duration {
  41. d := time.Since(t.started)
  42. if len(events) == 0 {
  43. if t.name == "" {
  44. panic("no name or events specified")
  45. }
  46. t.addDuration(t.name, d)
  47. } else {
  48. for _, e := range events {
  49. if t.name != "" {
  50. e = t.name + "/" + e
  51. }
  52. t.addDuration(e, d)
  53. }
  54. }
  55. return d
  56. }
  57. func (t *Timer) MarkOk(ok bool) {
  58. if ok {
  59. t.Mark("ok")
  60. } else {
  61. t.Mark("not ok")
  62. }
  63. }
  64. func (t *Timer) MarkErr(err error) {
  65. if err == nil {
  66. t.Mark("success")
  67. } else {
  68. t.Mark("error")
  69. }
  70. }
  71. func (t *Timer) addDuration(desc string, d time.Duration) {
  72. t.marked = true
  73. mu.RLock()
  74. e := events[desc]
  75. mu.RUnlock()
  76. if e == nil {
  77. mu.Lock()
  78. e = events[desc]
  79. if e == nil {
  80. e = new(Event)
  81. e.Init()
  82. events[desc] = e
  83. }
  84. mu.Unlock()
  85. }
  86. e.Add(d)
  87. if t.log {
  88. if t.name != "" {
  89. log.Printf("timer %q got event %q after %s", t.name, desc, d)
  90. } else {
  91. log.Printf("marking event %q after %s", desc, d)
  92. }
  93. }
  94. }