1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
require 'atomic'
require 'metriks/uniform_sample'
require 'metriks/exponentially_decaying_sample'
module Metriks
class Histogram
DEFAULT_SAMPLE_SIZE = 1028
DEFAULT_ALPHA = 0.015
def self.new_uniform
new(Metriks::UniformSample.new(DEFAULT_SAMPLE_SIZE))
end
def self.new_exponentially_decaying
new(Metriks::ExponentiallyDecayingSample.new(DEFAULT_SAMPLE_SIZE, DEFAULT_ALPHA))
end
def initialize(sample)
@sample = sample
@count = Atomic.new(0)
@min = Atomic.new(nil)
@max = Atomic.new(nil)
@sum = Atomic.new(0)
@variance = Atomic.new([ -1, 0 ])
end
def clear
@sample.clear
@count.value = 0
@min.value = nil
@max.value = nil
@sum.value = 0
@variance.value = [ -1, 0 ]
end
def update(value)
@count.update { |v| v + 1 }
@sample.update(value)
self.max = value
self.min = value
@sum.update { |v| v + value }
update_variance(value)
end
def snapshot
@sample.snapshot
end
def count
@count.value
end
def sum
@sum.value
end
def max
count > 0 ? @max.value : 0.0
end
def min
count > 0 ? @min.value : 0.0
end
def mean
count > 0 ? @sum.value / count : 0.0
end
def stddev
count > 0 ? variance ** 0.5 : 0.0
end
def variance
count <= 1 ? 0.0 : @variance.value[1] / (count - 1)
end
def max=(potential_max)
done = false
while !done
current_max = @max.value
done = (!current_max.nil? && current_max >= potential_max) || @max.compare_and_swap(current_max, potential_max)
end
end
def min=(potential_min)
done = false
while !done
current_min = @min.value
done = (!current_min.nil? && current_min <= potential_min) || @min.compare_and_swap(current_min, potential_min)
end
end
def update_variance(value)
@variance.update do |old_values|
new_values = Array.new(2)
if old_values[0] == -1
new_values[0] = value
new_values[1] = 0
else
old_m = old_values[0]
old_s = old_values[1]
new_m = old_m + ((value - old_m) / count)
new_s = old_s + ((value - old_m) * (value - new_m))
new_values[0] = new_m
new_values[1] = new_s
end
new_values
end
end
end
end
|