github.com/sereiner/library@v0.0.0-20200518095232-1fa3e640cc5f/metrics/rpsc.go (about) 1 package metrics 2 3 import ( 4 "sync/atomic" 5 "time" 6 ) 7 8 //QPSC 基于HashedWheelTimer算法的计数器,过期自动淘汰 9 type QPSC struct { 10 total int 11 length int 12 slots []int32 13 lastTicker int64 14 counter int32 15 } 16 17 //NewQPSC 构建计数器 18 func NewQPSC(length int, total int) (w *QPSC) { 19 w = &QPSC{length: length, total: total} 20 w.slots = make([]int32, w.total, w.total) 21 for i := 0; i < w.total; i++ { 22 w.slots[i] = 0 23 } 24 return w 25 } 26 27 //Mark 添加新值 28 func (r *QPSC) Mark(new int32) { 29 r.mark(new, time.Now().Unix()) 30 } 31 32 //mark 记录上次执行时间,超过时间间隔则清除counter 33 //每一跳需清除中间秒数 34 func (r *QPSC) mark(new int32, currentStep int64) { 35 lastStep := r.lastTicker 36 current := int(currentStep % int64(r.total)) 37 atomic.AddInt32(&r.counter, -r.clear(lastStep, currentStep)) //6, 8(clear,1,2,7,8) 38 atomic.AddInt32(&r.counter, new) 39 atomic.AddInt32(&r.slots[current], new) 40 r.lastTicker = currentStep 41 } 42 43 func (r *QPSC) clear(l int64, n int64) (clearCounter int32) { //1-5:1,10:1,10 //2:1,3:1 44 clearCounter = int32(0) 45 if l == n { 46 return 47 } 48 //清空时间中间差 49 if int(n-l) >= r.length { 50 for i := 0; i < r.total; i++ { 51 clearCounter += atomic.SwapInt32(&r.slots[i], 0) 52 } 53 return clearCounter 54 } 55 56 right := int(n % int64(r.total)) //0,3 57 l1 := (right - r.length + 1) % r.total //5,4 58 left := l1 % r.total 59 if l1 < 0 { 60 left = (l1 + r.total) % r.total 61 } 62 if right > left { 63 for i := 0; i < left; i++ { //0,1,2,3,4,5 64 clearCounter += atomic.SwapInt32(&r.slots[i], 0) 65 } 66 for i := right; i < r.total; i++ { //1, 67 clearCounter += atomic.SwapInt32(&r.slots[i], 0) 68 } 69 return clearCounter 70 } 71 for i := right; i < left; i++ { //0,1,2,3,4,5 //3,4 72 clearCounter += atomic.SwapInt32(&r.slots[i], 0) 73 } 74 return clearCounter 75 76 }