87 lines
1.5 KiB
Go
87 lines
1.5 KiB
Go
|
package stats
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
"sync/atomic"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type ElementCount struct {
|
||
|
Current int64
|
||
|
Total int64
|
||
|
Rps float64
|
||
|
LastRps float64
|
||
|
}
|
||
|
|
||
|
func NewRpsCounter() *RpsCounter {
|
||
|
return &RpsCounter{
|
||
|
mu: &sync.Mutex{},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type RpsCounter struct {
|
||
|
counter int64
|
||
|
lastAdd int64
|
||
|
start time.Time
|
||
|
stop time.Time
|
||
|
updated bool
|
||
|
mu *sync.Mutex
|
||
|
total int64
|
||
|
}
|
||
|
|
||
|
func (r *RpsCounter) Add(n int) {
|
||
|
atomic.AddInt64(&r.counter, int64(n))
|
||
|
atomic.AddInt64(&r.lastAdd, int64(n))
|
||
|
if n > 0 {
|
||
|
r.mu.Lock()
|
||
|
defer r.mu.Unlock()
|
||
|
if r.start.IsZero() {
|
||
|
r.start = time.Now()
|
||
|
}
|
||
|
r.updated = true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (r *RpsCounter) Value() int64 {
|
||
|
return atomic.LoadInt64(&r.counter)
|
||
|
}
|
||
|
|
||
|
func (r *RpsCounter) Rps() float64 {
|
||
|
r.mu.Lock()
|
||
|
defer r.mu.Unlock()
|
||
|
return float64(atomic.LoadInt64(&r.counter)) / float64(r.stop.Sub(r.start).Seconds())
|
||
|
}
|
||
|
|
||
|
func (r *RpsCounter) LastRps() float64 {
|
||
|
r.mu.Lock()
|
||
|
defer r.mu.Unlock()
|
||
|
return float64(atomic.LoadInt64(&r.lastAdd)) / float64(time.Since(r.stop).Seconds())
|
||
|
}
|
||
|
|
||
|
func (r *RpsCounter) Progress() float64 {
|
||
|
if r.total == 0 {
|
||
|
return -1.0
|
||
|
}
|
||
|
|
||
|
return float64(atomic.LoadInt64(&r.counter)) / float64(r.total)
|
||
|
}
|
||
|
|
||
|
func (r *RpsCounter) Count() ElementCount {
|
||
|
return ElementCount{
|
||
|
Current: r.Value(),
|
||
|
Total: r.total,
|
||
|
Rps: r.Rps(),
|
||
|
LastRps: r.LastRps(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (r *RpsCounter) Tick() {
|
||
|
r.mu.Lock()
|
||
|
defer r.mu.Unlock()
|
||
|
if r.updated {
|
||
|
r.stop = time.Now()
|
||
|
r.updated = false
|
||
|
}
|
||
|
atomic.StoreInt64(&r.lastAdd, 0)
|
||
|
}
|