瀏覽代碼

Merge remote-tracking branch 'artyom/master'

Richard Crowley 11 年之前
父節點
當前提交
3be59ceb55
共有 3 個文件被更改,包括 42 次插入5 次删除
  1. 1 1
      meter.go
  2. 10 4
      sample.go
  3. 31 0
      sample_test.go

+ 1 - 1
meter.go

@@ -193,7 +193,7 @@ func (m *StandardMeter) updateSnapshot() {
 	snapshot.rate1 = m.a1.Rate()
 	snapshot.rate5 = m.a5.Rate()
 	snapshot.rate15 = m.a15.Rate()
-	snapshot.rateMean = float64(1e9*snapshot.count) / float64(time.Since(m.startTime))
+	snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds()
 }
 
 func (m *StandardMeter) tick() {

+ 10 - 4
sample.go

@@ -6,7 +6,6 @@ import (
 	"math/rand"
 	"sort"
 	"sync"
-	"sync/atomic"
 	"time"
 )
 
@@ -74,7 +73,9 @@ func (s *ExpDecaySample) Clear() {
 // Count returns the number of samples recorded, which may exceed the
 // reservoir size.
 func (s *ExpDecaySample) Count() int64 {
-	return atomic.LoadInt64(&s.count)
+	s.mutex.Lock()
+	defer s.mutex.Unlock()
+	return s.count
 }
 
 // Max returns the maximum value in the sample, which may not be the maximum
@@ -401,7 +402,10 @@ func NewUniformSample(reservoirSize int) Sample {
 	if UseNilMetrics {
 		return NilSample{}
 	}
-	return &UniformSample{reservoirSize: reservoirSize}
+	return &UniformSample{
+		reservoirSize: reservoirSize,
+		values:        make([]int64, 0, reservoirSize),
+	}
 }
 
 // Clear clears all samples.
@@ -415,7 +419,9 @@ func (s *UniformSample) Clear() {
 // Count returns the number of samples recorded, which may exceed the
 // reservoir size.
 func (s *UniformSample) Count() int64 {
-	return atomic.LoadInt64(&s.count)
+	s.mutex.Lock()
+	defer s.mutex.Unlock()
+	return s.count
 }
 
 // Max returns the maximum value in the sample, which may not be the maximum

+ 31 - 0
sample_test.go

@@ -319,3 +319,34 @@ func testUniformSampleStatistics(t *testing.T, s Sample) {
 		t.Errorf("99th percentile: 9999.99 != %v\n", ps[2])
 	}
 }
+
+// TestUniformSampleConcurrentUpdateCount would expose data race problems with
+// concurrent Update and Count calls on Sample when test is called with -race
+// argument
+func TestUniformSampleConcurrentUpdateCount(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	s := NewUniformSample(100)
+	for i := 0; i < 100; i++ {
+		s.Update(int64(i))
+	}
+	quit := make(chan struct{})
+	go func() {
+		t := time.NewTicker(10 * time.Millisecond)
+		for {
+			select {
+			case <-t.C:
+				s.Update(rand.Int63())
+			case <-quit:
+				t.Stop()
+				return
+			}
+		}
+	}()
+	for i := 0; i < 1000; i++ {
+		s.Count()
+		time.Sleep(5 * time.Millisecond)
+	}
+	quit <- struct{}{}
+}