github.com/songzhibin97/gkit@v1.2.13/internal/stat/rolling_policy.go (about) 1 package stat 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 // RollingPolicy 基于持续时间的环形窗口的策略,随时间段移动存储桶偏移量。 9 type RollingPolicy struct { 10 mu sync.RWMutex 11 size int 12 window *Window 13 offset int 14 15 bucketDuration time.Duration 16 lastAppendTime time.Time 17 } 18 19 // timespan 时间跨度 20 func (r *RollingPolicy) timespan() int { 21 v := int(time.Since(r.lastAppendTime) / r.bucketDuration) 22 if v > -1 { 23 // 时钟回滚? 24 return v 25 } 26 return r.size 27 } 28 29 // add 30 func (r *RollingPolicy) add(f func(offset int, val float64), val float64) { 31 r.mu.Lock() 32 timespan := r.timespan() 33 if timespan > 0 { 34 r.lastAppendTime = r.lastAppendTime.Add(time.Duration(timespan * int(r.bucketDuration))) 35 offset := r.offset 36 // 重置过期的 bucket 37 s := offset + 1 38 if timespan > r.size { 39 timespan = r.size 40 } 41 // e: reset offset must start from offset+1 42 e, e1 := s+timespan, 0 43 if e > r.size { 44 e1 = e - r.size 45 e = r.size 46 } 47 for i := s; i < e; i++ { 48 r.window.ResetBucket(i) 49 offset = i 50 } 51 for i := 0; i < e1; i++ { 52 r.window.ResetBucket(i) 53 offset = i 54 } 55 r.offset = offset 56 } 57 f(r.offset, val) 58 r.mu.Unlock() 59 } 60 61 // Append 将给定的点附加到窗口 62 func (r *RollingPolicy) Append(val float64) { 63 r.add(r.window.Append, val) 64 } 65 66 // Add 将给定值添加到存储桶中的最新点 67 func (r *RollingPolicy) Add(val float64) { 68 r.add(r.window.Add, val) 69 } 70 71 // Reduce 缩减应用窗口 72 func (r *RollingPolicy) Reduce(f func(Iterator) float64) (val float64) { 73 r.mu.RLock() 74 timespan := r.timespan() 75 if count := r.size - timespan; count > 0 { 76 offset := r.offset + timespan + 1 77 if offset >= r.size { 78 offset = offset - r.size 79 } 80 val = f(r.window.Iterator(offset, count)) 81 } 82 r.mu.RUnlock() 83 return val 84 } 85 86 // NewRollingPolicy 实例化 RollingPolicy 对象 87 func NewRollingPolicy(window *Window, bucketDuration time.Duration) *RollingPolicy { 88 return &RollingPolicy{ 89 window: window, 90 size: window.Size(), 91 offset: 0, 92 93 bucketDuration: bucketDuration, 94 lastAppendTime: time.Now(), 95 } 96 }