try to fix int max perf counter bug

This commit is contained in:
Azareal 2020-02-27 11:45:07 +10:00
parent ea1037bd63
commit af7b6ebbcb

View File

@ -2,9 +2,8 @@ package counters
import ( import (
"database/sql" "database/sql"
"sync/atomic"
"time"
"math" "math"
"time"
c "github.com/Azareal/Gosora/common" c "github.com/Azareal/Gosora/common"
qgen "github.com/Azareal/Gosora/query_gen" qgen "github.com/Azareal/Gosora/query_gen"
@ -30,7 +29,7 @@ func NewDefaultPerfCounter(acc *qgen.Accumulator) (*DefaultPerfCounter, error) {
co := &DefaultPerfCounter{ co := &DefaultPerfCounter{
buckets: []PerfCounterBucket{ buckets: []PerfCounterBucket{
PerfCounterBucket{ PerfCounterBucket{
low: &MutexCounter64Bucket{counter: 0}, low: &MutexCounter64Bucket{counter: math.MaxInt64},
high: &MutexCounter64Bucket{counter: 0}, high: &MutexCounter64Bucket{counter: 0},
avg: &MutexCounter64Bucket{counter: 0}, avg: &MutexCounter64Bucket{counter: 0},
}, },
@ -45,11 +44,19 @@ func NewDefaultPerfCounter(acc *qgen.Accumulator) (*DefaultPerfCounter, error) {
} }
func (co *DefaultPerfCounter) Tick() error { func (co *DefaultPerfCounter) Tick() error {
getCounter := func(b *MutexCounter64Bucket) int64 { getCounter := func(b *MutexCounter64Bucket) (c int64) {
return atomic.SwapInt64(&b.counter, 0) b.Lock()
c = b.counter
b.counter = 0
b.Unlock()
return c
} }
for _, b := range co.buckets { for _, b := range co.buckets {
low := atomic.SwapInt64(&b.low.counter, math.MaxInt64) var low int64
b.low.Lock()
low = b.low.counter
b.low.counter = math.MaxInt64
b.low.Unlock()
if low == math.MaxInt64 { if low == math.MaxInt64 {
low = 0 low = 0
} }
@ -73,41 +80,34 @@ func (co *DefaultPerfCounter) insertChunk(low, high, avg int64) error {
return err return err
} }
func (co *DefaultPerfCounter) Push(dur time.Duration) { func (co *DefaultPerfCounter) Push(dur time.Duration /*_ bool*/) {
id := 0 id := 0
b := co.buckets[id] b := co.buckets[id]
//c.DebugDetail("co.buckets[", id, "]: ", b) //c.DebugDetail("buckets[", id, "]: ", b)
micro := dur.Microseconds() micro := dur.Microseconds()
low := b.low low := b.low
if micro < low.counter {
low.Lock() low.Lock()
if micro < low.counter { if micro < low.counter {
atomic.StoreInt64(&low.counter,micro) low.counter = micro
} }
low.Unlock() low.Unlock()
}
high := b.high high := b.high
if micro > high.counter {
high.Lock() high.Lock()
if micro > high.counter { if micro > high.counter {
atomic.StoreInt64(&high.counter,micro) high.counter = micro
} }
high.Unlock() high.Unlock()
}
avg := b.avg avg := b.avg
// TODO: Sync semantics are slightly loose but it should be close enough for our purposes here
if micro != avg.counter {
t := false
avg.Lock() avg.Lock()
if micro != avg.counter {
if avg.counter == 0 { if avg.counter == 0 {
t = atomic.CompareAndSwapInt64(&avg.counter, 0, micro) avg.counter = micro
} else {
avg.counter = (micro + avg.counter) / 2
} }
if !t && micro != avg.counter {
atomic.StoreInt64(&avg.counter,(micro+avg.counter) / 2)
} }
avg.Unlock() avg.Unlock()
} }
}