Thread safe, but unsafe

This commit is contained in:
Justin Li 2014-07-22 12:42:56 -04:00
parent a162f38281
commit ff77a29b0a
2 changed files with 26 additions and 9 deletions

View file

@ -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 {

View file

@ -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)
}