mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
metrics: separate updatable/readonly sample, runtimehistogram + do early sample calculation to avoid later iterations
This commit is contained in:
parent
7e6f1a6869
commit
9591faf40d
5 changed files with 81 additions and 311 deletions
|
|
@ -7,7 +7,7 @@ type HistogramSnapshot interface {
|
||||||
Min() int64
|
Min() int64
|
||||||
Percentile(float64) float64
|
Percentile(float64) float64
|
||||||
Percentiles([]float64) []float64
|
Percentiles([]float64) []float64
|
||||||
Sample() Sample
|
Sample() SampleSnapshot
|
||||||
StdDev() float64
|
StdDev() float64
|
||||||
Sum() int64
|
Sum() int64
|
||||||
Variance() float64
|
Variance() float64
|
||||||
|
|
@ -59,7 +59,7 @@ func NewRegisteredHistogram(name string, r Registry, s Sample) Histogram {
|
||||||
|
|
||||||
// histogramSnapshot is a read-only copy of another Histogram.
|
// histogramSnapshot is a read-only copy of another Histogram.
|
||||||
type histogramSnapshot struct {
|
type histogramSnapshot struct {
|
||||||
sample *SampleSnapshot
|
sample *sampleSnapshot
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the number of samples recorded at the time the snapshot was
|
// Count returns the number of samples recorded at the time the snapshot was
|
||||||
|
|
@ -91,7 +91,7 @@ func (h *histogramSnapshot) Percentiles(ps []float64) []float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample returns the Sample underlying the histogram.
|
// Sample returns the Sample underlying the histogram.
|
||||||
func (h *histogramSnapshot) Sample() Sample { return h.sample }
|
func (h *histogramSnapshot) Sample() SampleSnapshot { return h.sample }
|
||||||
|
|
||||||
// Snapshot returns the snapshot.
|
// Snapshot returns the snapshot.
|
||||||
func (h *histogramSnapshot) Snapshot() HistogramSnapshot { return h }
|
func (h *histogramSnapshot) Snapshot() HistogramSnapshot { return h }
|
||||||
|
|
@ -133,7 +133,7 @@ func (NilHistogram) Percentiles(ps []float64) []float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample is a no-op.
|
// Sample is a no-op.
|
||||||
func (NilHistogram) Sample() Sample { return NilSample{} }
|
func (NilHistogram) Sample() SampleSnapshot { return NilSample{} }
|
||||||
|
|
||||||
// Snapshot is a no-op.
|
// Snapshot is a no-op.
|
||||||
func (NilHistogram) Snapshot() HistogramSnapshot { return NilHistogram{} }
|
func (NilHistogram) Snapshot() HistogramSnapshot { return NilHistogram{} }
|
||||||
|
|
@ -161,7 +161,7 @@ func (h *StandardHistogram) Clear() { h.sample.Clear() }
|
||||||
|
|
||||||
// Snapshot returns a read-only copy of the histogram.
|
// Snapshot returns a read-only copy of the histogram.
|
||||||
func (h *StandardHistogram) Snapshot() HistogramSnapshot {
|
func (h *StandardHistogram) Snapshot() HistogramSnapshot {
|
||||||
return &histogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)}
|
return &histogramSnapshot{sample: h.sample.Snapshot().(*sampleSnapshot)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update samples a new value.
|
// Update samples a new value.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ type resettingSample struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snapshot returns a read-only copy of the sample with the original reset.
|
// Snapshot returns a read-only copy of the sample with the original reset.
|
||||||
func (rs *resettingSample) Snapshot() Sample {
|
func (rs *resettingSample) Snapshot() SampleSnapshot {
|
||||||
s := rs.Sample.Snapshot()
|
s := rs.Sample.Snapshot()
|
||||||
rs.Sample.Clear()
|
rs.Sample.Clear()
|
||||||
return s
|
return s
|
||||||
|
|
|
||||||
|
|
@ -57,69 +57,15 @@ func (h *runtimeHistogram) Clear() {
|
||||||
func (h *runtimeHistogram) Update(int64) {
|
func (h *runtimeHistogram) Update(int64) {
|
||||||
panic("runtimeHistogram does not support Update")
|
panic("runtimeHistogram does not support Update")
|
||||||
}
|
}
|
||||||
func (h *runtimeHistogram) Sample() Sample {
|
|
||||||
return NilSample{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Snapshot returns a non-changing cop of the histogram.
|
// Snapshot returns a non-changing cop of the histogram.
|
||||||
func (h *runtimeHistogram) Snapshot() HistogramSnapshot {
|
func (h *runtimeHistogram) Snapshot() HistogramSnapshot {
|
||||||
return h.load()
|
return h.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the sample count.
|
|
||||||
func (h *runtimeHistogram) Count() int64 {
|
|
||||||
return h.load().Count()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mean returns an approximation of the mean.
|
|
||||||
func (h *runtimeHistogram) Mean() float64 {
|
|
||||||
return h.load().Mean()
|
|
||||||
}
|
|
||||||
|
|
||||||
// StdDev approximates the standard deviation of the histogram.
|
|
||||||
func (h *runtimeHistogram) StdDev() float64 {
|
|
||||||
return h.load().StdDev()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variance approximates the variance of the histogram.
|
|
||||||
func (h *runtimeHistogram) Variance() float64 {
|
|
||||||
return h.load().Variance()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Percentile computes the p'th percentile value.
|
|
||||||
func (h *runtimeHistogram) Percentile(p float64) float64 {
|
|
||||||
return h.load().Percentile(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Percentiles computes all requested percentile values.
|
|
||||||
func (h *runtimeHistogram) Percentiles(ps []float64) []float64 {
|
|
||||||
return h.load().Percentiles(ps)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max returns the highest sample value.
|
|
||||||
func (h *runtimeHistogram) Max() int64 {
|
|
||||||
return h.load().Max()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min returns the lowest sample value.
|
|
||||||
func (h *runtimeHistogram) Min() int64 {
|
|
||||||
return h.load().Min()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sum returns the sum of all sample values.
|
|
||||||
func (h *runtimeHistogram) Sum() int64 {
|
|
||||||
return h.load().Sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
type runtimeHistogramSnapshot metrics.Float64Histogram
|
type runtimeHistogramSnapshot metrics.Float64Histogram
|
||||||
|
|
||||||
func (h *runtimeHistogramSnapshot) Clear() {
|
func (h *runtimeHistogramSnapshot) Sample() SampleSnapshot {
|
||||||
panic("runtimeHistogram does not support Clear")
|
|
||||||
}
|
|
||||||
func (h *runtimeHistogramSnapshot) Update(int64) {
|
|
||||||
panic("runtimeHistogram does not support Update")
|
|
||||||
}
|
|
||||||
func (h *runtimeHistogramSnapshot) Sample() Sample {
|
|
||||||
return NilSample{}
|
return NilSample{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,7 @@ import (
|
||||||
|
|
||||||
const rescaleThreshold = time.Hour
|
const rescaleThreshold = time.Hour
|
||||||
|
|
||||||
// Samples maintain a statistically-significant selection of values from
|
type SampleSnapshot interface {
|
||||||
// a stream.
|
|
||||||
type Sample interface {
|
|
||||||
Clear()
|
|
||||||
Count() int64
|
Count() int64
|
||||||
Max() int64
|
Max() int64
|
||||||
Mean() float64
|
Mean() float64
|
||||||
|
|
@ -22,14 +19,20 @@ type Sample interface {
|
||||||
Percentile(float64) float64
|
Percentile(float64) float64
|
||||||
Percentiles([]float64) []float64
|
Percentiles([]float64) []float64
|
||||||
Size() int
|
Size() int
|
||||||
Snapshot() Sample
|
|
||||||
StdDev() float64
|
StdDev() float64
|
||||||
Sum() int64
|
Sum() int64
|
||||||
Update(int64)
|
|
||||||
Values() []int64
|
Values() []int64
|
||||||
Variance() float64
|
Variance() float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Samples maintain a statistically-significant selection of values from
|
||||||
|
// a stream.
|
||||||
|
type Sample interface {
|
||||||
|
Snapshot() SampleSnapshot
|
||||||
|
Clear()
|
||||||
|
Update(int64)
|
||||||
|
}
|
||||||
|
|
||||||
// ExpDecaySample is an exponentially-decaying sample using a forward-decaying
|
// ExpDecaySample is an exponentially-decaying sample using a forward-decaying
|
||||||
// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time
|
// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time
|
||||||
// Decay Model for Streaming Systems".
|
// Decay Model for Streaming Systems".
|
||||||
|
|
@ -77,72 +80,16 @@ func (s *ExpDecaySample) Clear() {
|
||||||
s.values.Clear()
|
s.values.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the number of samples recorded, which may exceed the
|
|
||||||
// reservoir size.
|
|
||||||
func (s *ExpDecaySample) Count() int64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return s.count
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max returns the maximum value in the sample, which may not be the maximum
|
|
||||||
// value ever to be part of the sample.
|
|
||||||
func (s *ExpDecaySample) Max() int64 {
|
|
||||||
return SampleMax(s.Values())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mean returns the mean of the values in the sample.
|
|
||||||
func (s *ExpDecaySample) Mean() float64 {
|
|
||||||
return SampleMean(s.Values())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min returns the minimum value in the sample, which may not be the minimum
|
|
||||||
// value ever to be part of the sample.
|
|
||||||
func (s *ExpDecaySample) Min() int64 {
|
|
||||||
return SampleMin(s.Values())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Percentile returns an arbitrary percentile of values in the sample.
|
|
||||||
func (s *ExpDecaySample) Percentile(p float64) float64 {
|
|
||||||
return SamplePercentile(s.Values(), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Percentiles returns a slice of arbitrary percentiles of values in the
|
|
||||||
// sample.
|
|
||||||
func (s *ExpDecaySample) Percentiles(ps []float64) []float64 {
|
|
||||||
return SamplePercentiles(s.Values(), ps)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the size of the sample, which is at most the reservoir size.
|
|
||||||
func (s *ExpDecaySample) Size() int {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return s.values.Size()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Snapshot returns a read-only copy of the sample.
|
// Snapshot returns a read-only copy of the sample.
|
||||||
func (s *ExpDecaySample) Snapshot() Sample {
|
func (s *ExpDecaySample) Snapshot() SampleSnapshot {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.Unlock()
|
|
||||||
vals := s.values.Values()
|
vals := s.values.Values()
|
||||||
values := make([]int64, len(vals))
|
values := make([]int64, len(vals))
|
||||||
for i, v := range vals {
|
for i, v := range vals {
|
||||||
values[i] = v.v
|
values[i] = v.v
|
||||||
}
|
}
|
||||||
return &SampleSnapshot{
|
s.mutex.Unlock()
|
||||||
count: s.count,
|
return newSampleSnapshot(s.count, values)
|
||||||
values: values,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// StdDev returns the standard deviation of the values in the sample.
|
|
||||||
func (s *ExpDecaySample) StdDev() float64 {
|
|
||||||
return SampleStdDev(s.Values())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sum returns the sum of the values in the sample.
|
|
||||||
func (s *ExpDecaySample) Sum() int64 {
|
|
||||||
return SampleSum(s.Values())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update samples a new value.
|
// Update samples a new value.
|
||||||
|
|
@ -150,23 +97,6 @@ func (s *ExpDecaySample) Update(v int64) {
|
||||||
s.update(time.Now(), v)
|
s.update(time.Now(), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values returns a copy of the values in the sample.
|
|
||||||
func (s *ExpDecaySample) Values() []int64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
vals := s.values.Values()
|
|
||||||
values := make([]int64, len(vals))
|
|
||||||
for i, v := range vals {
|
|
||||||
values[i] = v.v
|
|
||||||
}
|
|
||||||
return values
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variance returns the variance of the values in the sample.
|
|
||||||
func (s *ExpDecaySample) Variance() float64 {
|
|
||||||
return SampleVariance(s.Values())
|
|
||||||
}
|
|
||||||
|
|
||||||
// update samples a new value at a particular timestamp. This is a method all
|
// update samples a new value at a particular timestamp. This is a method all
|
||||||
// its own to facilitate testing.
|
// its own to facilitate testing.
|
||||||
func (s *ExpDecaySample) update(t time.Time, v int64) {
|
func (s *ExpDecaySample) update(t time.Time, v int64) {
|
||||||
|
|
@ -229,7 +159,7 @@ func (NilSample) Percentiles(ps []float64) []float64 {
|
||||||
func (NilSample) Size() int { return 0 }
|
func (NilSample) Size() int { return 0 }
|
||||||
|
|
||||||
// Sample is a no-op.
|
// Sample is a no-op.
|
||||||
func (NilSample) Snapshot() Sample { return NilSample{} }
|
func (NilSample) Snapshot() SampleSnapshot { return NilSample{} }
|
||||||
|
|
||||||
// StdDev is a no-op.
|
// StdDev is a no-op.
|
||||||
func (NilSample) StdDev() float64 { return 0.0 }
|
func (NilSample) StdDev() float64 { return 0.0 }
|
||||||
|
|
@ -246,42 +176,6 @@ func (NilSample) Values() []int64 { return []int64{} }
|
||||||
// Variance is a no-op.
|
// Variance is a no-op.
|
||||||
func (NilSample) Variance() float64 { return 0.0 }
|
func (NilSample) Variance() float64 { return 0.0 }
|
||||||
|
|
||||||
// SampleMax returns the maximum value of the slice of int64.
|
|
||||||
func SampleMax(values []int64) int64 {
|
|
||||||
if len(values) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
var max int64 = math.MinInt64
|
|
||||||
for _, v := range values {
|
|
||||||
if max < v {
|
|
||||||
max = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
|
|
||||||
// SampleMean returns the mean value of the slice of int64.
|
|
||||||
func SampleMean(values []int64) float64 {
|
|
||||||
if len(values) == 0 {
|
|
||||||
return 0.0
|
|
||||||
}
|
|
||||||
return float64(SampleSum(values)) / float64(len(values))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SampleMin returns the minimum value of the slice of int64.
|
|
||||||
func SampleMin(values []int64) int64 {
|
|
||||||
if len(values) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
var min int64 = math.MaxInt64
|
|
||||||
for _, v := range values {
|
|
||||||
if min > v {
|
|
||||||
min = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return min
|
|
||||||
}
|
|
||||||
|
|
||||||
// SamplePercentiles returns an arbitrary percentile of the slice of int64.
|
// SamplePercentiles returns an arbitrary percentile of the slice of int64.
|
||||||
func SamplePercentile(values []int64, p float64) float64 {
|
func SamplePercentile(values []int64, p float64) float64 {
|
||||||
return SamplePercentiles(values, []float64{p})[0]
|
return SamplePercentiles(values, []float64{p})[0]
|
||||||
|
|
@ -310,99 +204,108 @@ func SamplePercentiles(values []int64, ps []float64) []float64 {
|
||||||
return scores
|
return scores
|
||||||
}
|
}
|
||||||
|
|
||||||
// SampleSnapshot is a read-only copy of another Sample.
|
// sampleSnapshot is a read-only copy of another Sample.
|
||||||
type SampleSnapshot struct {
|
type sampleSnapshot struct {
|
||||||
count int64
|
count int64
|
||||||
values []int64
|
values []int64
|
||||||
|
|
||||||
|
max int64
|
||||||
|
min int64
|
||||||
|
mean float64
|
||||||
|
sum int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot {
|
// newSampleSnapshot creates a read-only sampleSnapShot, and calculates some
|
||||||
return &SampleSnapshot{
|
// numbers.
|
||||||
|
func newSampleSnapshot(count int64, values []int64) *sampleSnapshot {
|
||||||
|
s := &sampleSnapshot{
|
||||||
count: count,
|
count: count,
|
||||||
values: values,
|
values: values,
|
||||||
}
|
}
|
||||||
}
|
if len(values) == 0 {
|
||||||
|
return s
|
||||||
// Clear panics.
|
}
|
||||||
func (*SampleSnapshot) Clear() {
|
var (
|
||||||
panic("Clear called on a SampleSnapshot")
|
max int64 = math.MinInt64
|
||||||
|
min int64 = math.MaxInt64
|
||||||
|
sum int64
|
||||||
|
)
|
||||||
|
for _, v := range values {
|
||||||
|
sum += v
|
||||||
|
if v > max {
|
||||||
|
max = v
|
||||||
|
}
|
||||||
|
if v < min {
|
||||||
|
min = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.min = min
|
||||||
|
s.max = max
|
||||||
|
s.mean = float64(sum) / float64(len(values))
|
||||||
|
s.sum = sum
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the count of inputs at the time the snapshot was taken.
|
// Count returns the count of inputs at the time the snapshot was taken.
|
||||||
func (s *SampleSnapshot) Count() int64 { return s.count }
|
func (s *sampleSnapshot) Count() int64 { return s.count }
|
||||||
|
|
||||||
// Max returns the maximal value at the time the snapshot was taken.
|
// Max returns the maximal value at the time the snapshot was taken.
|
||||||
func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) }
|
func (s *sampleSnapshot) Max() int64 { return s.max }
|
||||||
|
|
||||||
// Mean returns the mean value at the time the snapshot was taken.
|
// Mean returns the mean value at the time the snapshot was taken.
|
||||||
func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) }
|
func (s *sampleSnapshot) Mean() float64 { return s.mean }
|
||||||
|
|
||||||
// Min returns the minimal value at the time the snapshot was taken.
|
// Min returns the minimal value at the time the snapshot was taken.
|
||||||
func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) }
|
func (s *sampleSnapshot) Min() int64 { return s.min }
|
||||||
|
|
||||||
// Percentile returns an arbitrary percentile of values at the time the
|
// Percentile returns an arbitrary percentile of values at the time the
|
||||||
// snapshot was taken.
|
// snapshot was taken.
|
||||||
func (s *SampleSnapshot) Percentile(p float64) float64 {
|
func (s *sampleSnapshot) Percentile(p float64) float64 {
|
||||||
return SamplePercentile(s.values, p)
|
return SamplePercentile(s.values, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Percentiles returns a slice of arbitrary percentiles of values at the time
|
// Percentiles returns a slice of arbitrary percentiles of values at the time
|
||||||
// the snapshot was taken.
|
// the snapshot was taken.
|
||||||
func (s *SampleSnapshot) Percentiles(ps []float64) []float64 {
|
func (s *sampleSnapshot) Percentiles(ps []float64) []float64 {
|
||||||
return SamplePercentiles(s.values, ps)
|
return SamplePercentiles(s.values, ps)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the size of the sample at the time the snapshot was taken.
|
// Size returns the size of the sample at the time the snapshot was taken.
|
||||||
func (s *SampleSnapshot) Size() int { return len(s.values) }
|
func (s *sampleSnapshot) Size() int { return len(s.values) }
|
||||||
|
|
||||||
// Snapshot returns the snapshot.
|
// Snapshot returns the snapshot.
|
||||||
func (s *SampleSnapshot) Snapshot() Sample { return s }
|
func (s *sampleSnapshot) Snapshot() SampleSnapshot { return s }
|
||||||
|
|
||||||
// StdDev returns the standard deviation of values at the time the snapshot was
|
// StdDev returns the standard deviation of values at the time the snapshot was
|
||||||
// taken.
|
// taken.
|
||||||
func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) }
|
func (s *sampleSnapshot) StdDev() float64 { return SampleStdDev(s.mean, s.values) }
|
||||||
|
|
||||||
// Sum returns the sum of values at the time the snapshot was taken.
|
// Sum returns the sum of values at the time the snapshot was taken.
|
||||||
func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) }
|
func (s *sampleSnapshot) Sum() int64 { return s.sum }
|
||||||
|
|
||||||
// Update panics.
|
|
||||||
func (*SampleSnapshot) Update(int64) {
|
|
||||||
panic("Update called on a SampleSnapshot")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values returns a copy of the values in the sample.
|
// Values returns a copy of the values in the sample.
|
||||||
func (s *SampleSnapshot) Values() []int64 {
|
func (s *sampleSnapshot) Values() []int64 {
|
||||||
values := make([]int64, len(s.values))
|
values := make([]int64, len(s.values))
|
||||||
copy(values, s.values)
|
copy(values, s.values)
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variance returns the variance of values at the time the snapshot was taken.
|
// Variance returns the variance of values at the time the snapshot was taken.
|
||||||
func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) }
|
func (s *sampleSnapshot) Variance() float64 { return SampleVariance(s.mean, s.values) }
|
||||||
|
|
||||||
// SampleStdDev returns the standard deviation of the slice of int64.
|
// SampleStdDev returns the standard deviation of the slice of int64.
|
||||||
func SampleStdDev(values []int64) float64 {
|
func SampleStdDev(mean float64, values []int64) float64 {
|
||||||
return math.Sqrt(SampleVariance(values))
|
return math.Sqrt(SampleVariance(mean, values))
|
||||||
}
|
|
||||||
|
|
||||||
// SampleSum returns the sum of the slice of int64.
|
|
||||||
func SampleSum(values []int64) int64 {
|
|
||||||
var sum int64
|
|
||||||
for _, v := range values {
|
|
||||||
sum += v
|
|
||||||
}
|
|
||||||
return sum
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SampleVariance returns the variance of the slice of int64.
|
// SampleVariance returns the variance of the slice of int64.
|
||||||
func SampleVariance(values []int64) float64 {
|
func SampleVariance(mean float64, values []int64) float64 {
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
return 0.0
|
return 0.0
|
||||||
}
|
}
|
||||||
m := SampleMean(values)
|
|
||||||
var sum float64
|
var sum float64
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
d := float64(v) - m
|
d := float64(v) - mean
|
||||||
sum += d * d
|
sum += d * d
|
||||||
}
|
}
|
||||||
return sum / float64(len(values))
|
return sum / float64(len(values))
|
||||||
|
|
@ -445,83 +348,13 @@ func (s *UniformSample) Clear() {
|
||||||
s.values = make([]int64, 0, s.reservoirSize)
|
s.values = make([]int64, 0, s.reservoirSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the number of samples recorded, which may exceed the
|
|
||||||
// reservoir size.
|
|
||||||
func (s *UniformSample) Count() int64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return s.count
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max returns the maximum value in the sample, which may not be the maximum
|
|
||||||
// value ever to be part of the sample.
|
|
||||||
func (s *UniformSample) Max() int64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return SampleMax(s.values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mean returns the mean of the values in the sample.
|
|
||||||
func (s *UniformSample) Mean() float64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return SampleMean(s.values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min returns the minimum value in the sample, which may not be the minimum
|
|
||||||
// value ever to be part of the sample.
|
|
||||||
func (s *UniformSample) Min() int64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return SampleMin(s.values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Percentile returns an arbitrary percentile of values in the sample.
|
|
||||||
func (s *UniformSample) Percentile(p float64) float64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return SamplePercentile(s.values, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Percentiles returns a slice of arbitrary percentiles of values in the
|
|
||||||
// sample.
|
|
||||||
func (s *UniformSample) Percentiles(ps []float64) []float64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return SamplePercentiles(s.values, ps)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size returns the size of the sample, which is at most the reservoir size.
|
|
||||||
func (s *UniformSample) Size() int {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return len(s.values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Snapshot returns a read-only copy of the sample.
|
// Snapshot returns a read-only copy of the sample.
|
||||||
func (s *UniformSample) Snapshot() Sample {
|
func (s *UniformSample) Snapshot() SampleSnapshot {
|
||||||
s.mutex.Lock()
|
s.mutex.Lock()
|
||||||
defer s.mutex.Unlock()
|
|
||||||
values := make([]int64, len(s.values))
|
values := make([]int64, len(s.values))
|
||||||
copy(values, s.values)
|
copy(values, s.values)
|
||||||
return &SampleSnapshot{
|
s.mutex.Unlock()
|
||||||
count: s.count,
|
return newSampleSnapshot(s.count, s.values)
|
||||||
values: values,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// StdDev returns the standard deviation of the values in the sample.
|
|
||||||
func (s *UniformSample) StdDev() float64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return SampleStdDev(s.values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sum returns the sum of the values in the sample.
|
|
||||||
func (s *UniformSample) Sum() int64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return SampleSum(s.values)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update samples a new value.
|
// Update samples a new value.
|
||||||
|
|
@ -544,22 +377,6 @@ func (s *UniformSample) Update(v int64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values returns a copy of the values in the sample.
|
|
||||||
func (s *UniformSample) Values() []int64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
values := make([]int64, len(s.values))
|
|
||||||
copy(values, s.values)
|
|
||||||
return values
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variance returns the variance of the values in the sample.
|
|
||||||
func (s *UniformSample) Variance() float64 {
|
|
||||||
s.mutex.Lock()
|
|
||||||
defer s.mutex.Unlock()
|
|
||||||
return SampleVariance(s.values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// expDecaySample represents an individual sample in a heap.
|
// expDecaySample represents an individual sample in a heap.
|
||||||
type expDecaySample struct {
|
type expDecaySample struct {
|
||||||
k float64
|
k float64
|
||||||
|
|
|
||||||
|
|
@ -14,22 +14,29 @@ import (
|
||||||
// computation for small samples and only slightly less for large samples.
|
// computation for small samples and only slightly less for large samples.
|
||||||
func BenchmarkCompute1000(b *testing.B) {
|
func BenchmarkCompute1000(b *testing.B) {
|
||||||
s := make([]int64, 1000)
|
s := make([]int64, 1000)
|
||||||
|
var sum int64
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
s[i] = int64(i)
|
s[i] = int64(i)
|
||||||
|
sum += int64(i)
|
||||||
}
|
}
|
||||||
|
mean := float64(sum) / float64(len(s))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
SampleVariance(s)
|
SampleVariance(mean, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func BenchmarkCompute1000000(b *testing.B) {
|
func BenchmarkCompute1000000(b *testing.B) {
|
||||||
s := make([]int64, 1000000)
|
s := make([]int64, 1000000)
|
||||||
|
var sum int64
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
s[i] = int64(i)
|
s[i] = int64(i)
|
||||||
|
sum += int64(i)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
mean := float64(sum) / float64(len(s))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
SampleVariance(s)
|
SampleVariance(mean, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func BenchmarkCopy1000(b *testing.B) {
|
func BenchmarkCopy1000(b *testing.B) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue