github.com/haraldrudell/parl@v0.4.176/counter/averager.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package counter
     7  
     8  import "time"
     9  
    10  // Averager is a fixed-sized 64-bit container returning float64 averages per time
    11  type Averager struct {
    12  	values []datapoint
    13  	n      int
    14  	size   int
    15  }
    16  
    17  type datapoint struct {
    18  	value    uint64
    19  	duration time.Duration
    20  }
    21  
    22  // NewAverager returns an 64-bit averager over size values
    23  func NewAverager(size int) (averager *Averager) {
    24  	return &Averager{
    25  		values: make([]datapoint, size),
    26  		size:   size,
    27  	}
    28  }
    29  
    30  // Add adds a new value and computes current average
    31  func (av *Averager) Add(value uint64, duration time.Duration) (average float64) {
    32  	if av.n < av.size {
    33  		// slice not full, use another position
    34  		var dpp = &av.values[av.n]
    35  		dpp.value = value
    36  		dpp.duration = duration
    37  		av.n++
    38  	} else {
    39  		copy(av.values, av.values[1:]) // drop the oldest value
    40  		var dpp = &av.values[av.n-1]
    41  		dpp.value = value
    42  		dpp.duration = duration
    43  	}
    44  
    45  	var valueTotal float64
    46  	var durationTotal time.Duration
    47  	for i := 0; i < av.n; i++ {
    48  		valueTotal += float64(av.values[i].value)
    49  		durationTotal += av.values[i].duration
    50  	}
    51  	average = valueTotal / durationTotal.Seconds()
    52  	return
    53  }