fix: harden single-machine load handling
This commit is contained in:
@@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -13,11 +13,10 @@ var latencyBounds = []time.Duration{
|
||||
}
|
||||
|
||||
type DurationHistogram struct {
|
||||
mu sync.Mutex
|
||||
count int64
|
||||
sum time.Duration
|
||||
max time.Duration
|
||||
bucket []int64
|
||||
count atomic.Int64
|
||||
sum atomic.Int64
|
||||
max atomic.Int64
|
||||
bucket []atomic.Int64
|
||||
}
|
||||
|
||||
type HistogramSnapshot struct {
|
||||
@@ -28,37 +27,36 @@ type HistogramSnapshot struct {
|
||||
}
|
||||
|
||||
func NewDurationHistogram() *DurationHistogram {
|
||||
return &DurationHistogram{bucket: make([]int64, len(latencyBounds)+1)}
|
||||
return &DurationHistogram{bucket: make([]atomic.Int64, len(latencyBounds)+1)}
|
||||
}
|
||||
|
||||
func (h *DurationHistogram) Observe(value time.Duration) {
|
||||
if value < 0 {
|
||||
return
|
||||
}
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
h.count++
|
||||
h.sum += value
|
||||
if value > h.max {
|
||||
h.max = value
|
||||
nanos := int64(value)
|
||||
h.count.Add(1)
|
||||
h.sum.Add(nanos)
|
||||
for previous := h.max.Load(); nanos > previous; previous = h.max.Load() {
|
||||
if h.max.CompareAndSwap(previous, nanos) {
|
||||
break
|
||||
}
|
||||
}
|
||||
idx := sort.Search(len(latencyBounds), func(i int) bool { return value <= latencyBounds[i] })
|
||||
h.bucket[idx]++
|
||||
h.bucket[idx].Add(1)
|
||||
}
|
||||
|
||||
func (h *DurationHistogram) Snapshot() HistogramSnapshot {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
buckets := make(map[string]int64, len(h.bucket))
|
||||
for i, count := range h.bucket {
|
||||
for i := range h.bucket {
|
||||
label := "+Inf"
|
||||
if i < len(latencyBounds) {
|
||||
label = latencyBounds[i].String()
|
||||
}
|
||||
buckets[label] = count
|
||||
buckets[label] = h.bucket[i].Load()
|
||||
}
|
||||
return HistogramSnapshot{
|
||||
Count: h.count, SumMS: float64(h.sum) / float64(time.Millisecond),
|
||||
MaxMS: float64(h.max) / float64(time.Millisecond), Buckets: buckets,
|
||||
Count: h.count.Load(), SumMS: float64(h.sum.Load()) / float64(time.Millisecond),
|
||||
MaxMS: float64(h.max.Load()) / float64(time.Millisecond), Buckets: buckets,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user