github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/metrics/ewma.go (about)

     1  package metrics
     2  
     3  import (
     4  	"math"
     5  	"sync"
     6  	"sync/atomic"
     7  )
     8  
     9  type EWMA interface {
    10  	Rate() float64
    11  	Snapshot() EWMA
    12  	Tick()
    13  	Update(int64)
    14  }
    15  
    16  func NewEWMA(alpha float64) EWMA {
    17  	if !Enabled {
    18  		return NilEWMA{}
    19  	}
    20  	return &StandardEWMA{alpha: alpha}
    21  }
    22  
    23  func NewEWMA1() EWMA {
    24  	return NewEWMA(1 - math.Exp(-5.0/60.0/1))
    25  }
    26  
    27  func NewEWMA5() EWMA {
    28  	return NewEWMA(1 - math.Exp(-5.0/60.0/5))
    29  }
    30  
    31  func NewEWMA15() EWMA {
    32  	return NewEWMA(1 - math.Exp(-5.0/60.0/15))
    33  }
    34  
    35  type EWMASnapshot float64
    36  
    37  func (a EWMASnapshot) Rate() float64 { return float64(a) }
    38  
    39  func (a EWMASnapshot) Snapshot() EWMA { return a }
    40  
    41  func (EWMASnapshot) Tick() {
    42  	panic("Tick called on an EWMASnapshot")
    43  }
    44  
    45  func (EWMASnapshot) Update(int64) {
    46  	panic("Update called on an EWMASnapshot")
    47  }
    48  
    49  type NilEWMA struct{}
    50  
    51  func (NilEWMA) Rate() float64 { return 0.0 }
    52  
    53  func (NilEWMA) Snapshot() EWMA { return NilEWMA{} }
    54  
    55  func (NilEWMA) Tick() {}
    56  
    57  func (NilEWMA) Update(n int64) {}
    58  
    59  type StandardEWMA struct {
    60  	uncounted int64
    61  	alpha     float64
    62  	rate      float64
    63  	init      bool
    64  	mutex     sync.Mutex
    65  }
    66  
    67  func (a *StandardEWMA) Rate() float64 {
    68  	a.mutex.Lock()
    69  	defer a.mutex.Unlock()
    70  	return a.rate * float64(1e9)
    71  }
    72  
    73  func (a *StandardEWMA) Snapshot() EWMA {
    74  	return EWMASnapshot(a.Rate())
    75  }
    76  
    77  func (a *StandardEWMA) Tick() {
    78  	count := atomic.LoadInt64(&a.uncounted)
    79  	atomic.AddInt64(&a.uncounted, -count)
    80  	instantRate := float64(count) / float64(5e9)
    81  	a.mutex.Lock()
    82  	defer a.mutex.Unlock()
    83  	if a.init {
    84  		a.rate += a.alpha * (instantRate - a.rate)
    85  	} else {
    86  		a.init = true
    87  		a.rate = instantRate
    88  	}
    89  }
    90  
    91  func (a *StandardEWMA) Update(n int64) {
    92  	atomic.AddInt64(&a.uncounted, n)
    93  }