1
Fork 0
galene/estimator/estimator.go

75 lines
1.5 KiB
Go
Raw Normal View History

2020-04-30 20:15:52 +02:00
package estimator
import (
"sync"
"sync/atomic"
"time"
)
type Estimator struct {
interval time.Duration
bytes uint32
packets uint32
2020-04-30 20:15:52 +02:00
2020-05-31 23:54:55 +02:00
mu sync.Mutex
totalBytes uint32
totalPackets uint32
rate uint32
packetRate uint32
2020-05-31 23:54:55 +02:00
time time.Time
2020-04-30 20:15:52 +02:00
}
func New(interval time.Duration) *Estimator {
return &Estimator{
interval: interval,
time: time.Now(),
}
}
func (e *Estimator) swap(now time.Time) {
interval := now.Sub(e.time)
bytes := atomic.SwapUint32(&e.bytes, 0)
packets := atomic.SwapUint32(&e.packets, 0)
atomic.AddUint32(&e.totalBytes, bytes)
atomic.AddUint32(&e.totalPackets, packets)
2020-04-30 20:15:52 +02:00
if interval < time.Millisecond {
e.rate = 0
e.packetRate = 0
2020-04-30 20:15:52 +02:00
} else {
e.rate = uint32(uint64(bytes*1000) /
uint64(interval/time.Millisecond))
e.packetRate = uint32(uint64(packets*1000) /
uint64(interval/time.Millisecond))
2020-04-30 20:15:52 +02:00
}
e.time = now
}
2020-05-31 23:47:12 +02:00
func (e *Estimator) Accumulate(count uint32) {
atomic.AddUint32(&e.bytes, count)
atomic.AddUint32(&e.packets, 1)
2020-04-30 20:15:52 +02:00
}
func (e *Estimator) estimate(now time.Time) (uint32, uint32) {
2020-04-30 20:15:52 +02:00
if now.Sub(e.time) > e.interval {
e.swap(now)
}
return e.rate, e.packetRate
2020-04-30 20:15:52 +02:00
}
func (e *Estimator) Estimate() (uint32, uint32) {
2020-04-30 20:15:52 +02:00
now := time.Now()
e.mu.Lock()
defer e.mu.Unlock()
return e.estimate(now)
}
2020-05-31 23:54:55 +02:00
func (e *Estimator) Totals() (uint32, uint32) {
b := atomic.LoadUint32(&e.totalBytes) + atomic.LoadUint32(&e.bytes)
p := atomic.LoadUint32(&e.totalPackets) + atomic.LoadUint32(&e.packets)
2020-05-31 23:54:55 +02:00
return p, b
}