Thread safe, but unsafe
This commit is contained in:
parent
a162f38281
commit
ff77a29b0a
2 changed files with 26 additions and 9 deletions
|
@ -3,6 +3,8 @@ package stats
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
"sync/atomic"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Percentile struct {
|
type Percentile struct {
|
||||||
|
@ -10,17 +12,23 @@ type Percentile struct {
|
||||||
|
|
||||||
samples int64
|
samples int64
|
||||||
offset int64
|
offset int64
|
||||||
|
|
||||||
values []float64
|
values []float64
|
||||||
|
value *unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPercentile(percentile float64, sampleWindow int) *Percentile {
|
func NewPercentile(percentile float64, sampleWindow int) *Percentile {
|
||||||
|
initial := 0
|
||||||
|
ptr := unsafe.Pointer(&initial)
|
||||||
|
|
||||||
return &Percentile{
|
return &Percentile{
|
||||||
percentile: percentile,
|
percentile: percentile,
|
||||||
|
|
||||||
values: make([]float64, 0, sampleWindow),
|
values: make([]float64, 0, sampleWindow),
|
||||||
|
value: &ptr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not thread safe.
|
|
||||||
func (p *Percentile) AddSample(sample float64) {
|
func (p *Percentile) AddSample(sample float64) {
|
||||||
p.samples++
|
p.samples++
|
||||||
|
|
||||||
|
@ -55,14 +63,14 @@ func (p *Percentile) AddSample(sample float64) {
|
||||||
copy(p.values[idx+1:], p.values[idx:])
|
copy(p.values[idx+1:], p.values[idx:])
|
||||||
p.values[idx] = sample
|
p.values[idx] = sample
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value := p.values[p.index()]
|
||||||
|
atomic.SwapPointer(p.value, unsafe.Pointer(&value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Percentile) Value() float64 {
|
func (p *Percentile) Value() float64 {
|
||||||
if len(p.values) == 0 {
|
pointer := atomic.LoadPointer(p.value)
|
||||||
return 0
|
return *(*float64)(pointer)
|
||||||
}
|
|
||||||
|
|
||||||
return p.values[p.index()]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Percentile) index() int64 {
|
func (p *Percentile) index() int64 {
|
||||||
|
|
|
@ -106,6 +106,10 @@ func (s *Stats) RecordEvent(event int) {
|
||||||
s.events <- event
|
s.events <- event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Stats) RecordTiming(event int, duration time.Duration) {
|
||||||
|
// s.timingEvents <- event
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Stats) handleEvents() {
|
func (s *Stats) handleEvents() {
|
||||||
for event := range s.events {
|
for event := range s.events {
|
||||||
switch event {
|
switch event {
|
||||||
|
@ -178,7 +182,12 @@ func (s *Stats) handleEvents() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecordEvent broadcasts an event to the default stats tracking.
|
// RecordEvent broadcasts an event to the default stats queue.
|
||||||
func RecordEvent(event int) {
|
func RecordEvent(event int) {
|
||||||
DefaultStats.RecordEvent(event)
|
DefaultStats.RecordEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RecordTiming broadcasts a timing event to the default stats queue.
|
||||||
|
func RecordTiming(event int, duration time.Duration) {
|
||||||
|
DefaultStats.RecordTiming(event, duration)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue