class Spectator::Histogram::PercentileBuckets

rubocop: disable Metrics/ClassLength

Constants

MAX_VALUE

rubocop:enable Metrics/ClassLength

Public Class Methods

bucket(value) click to toggle source
# File lib/spectator/histogram/percentiles.rb, line 374
def self.bucket(value)
  @bucket_values[index_of(value)]
end
check_perc_args(counts, pcts, results) click to toggle source
# File lib/spectator/histogram/percentiles.rb, line 421
def self.check_perc_args(counts, pcts, results)
  if counts.length != length
    raise ArgumentError(
      'counts is not the same size as the buckets array'
    )
  end

  raise ArgumentError('pcts cannot be empty') if pcts.empty?

  raise ArgumentError('pcts is not the same size as the results array') if
      pcts.length != results.length
end
counters(registry, id, prefix) click to toggle source
# File lib/spectator/histogram/percentiles.rb, line 412
def self.counters(registry, id, prefix)
  (0...length).map do |i|
    tags = { statistic: 'percentile',
             percentile: prefix + format('%<idx>04X', idx: i) }
    counter_id = id.with_tags(tags)
    registry.counter_with_id(counter_id)
  end
end
get(index) click to toggle source
# File lib/spectator/histogram/percentiles.rb, line 370
def self.get(index)
  @bucket_values[index]
end
index_of(value) click to toggle source

rubocop: disable Metrics/MethodLength

# File lib/spectator/histogram/percentiles.rb, line 339
def self.index_of(value)
  if value <= 0
    0
  elsif value <= 4
    value
  else
    lz = num_leading_zeros(value)
    shift = 64 - lz - 1
    prev_pwr2 = (value >> shift) << shift
    prev_pwr4 = prev_pwr2
    if shift.odd?
      shift -= 1
      prev_pwr4 >>= 1
    end
    base = prev_pwr4
    delta = base / 3
    offset = (value - base) / delta
    pos = offset + @power_of_4_index[shift / 2]
    if pos >= length - 1
      length - 1
    else
      pos + 1
    end
  end
end
length() click to toggle source

rubocop: enable Metrics/MethodLength

# File lib/spectator/histogram/percentiles.rb, line 366
def self.length
  @bucket_values.length
end
num_leading_zeros(value) click to toggle source
# File lib/spectator/histogram/percentiles.rb, line 329
def self.num_leading_zeros(value)
  leading = 64
  while value.positive?
    value >>= 1
    leading -= 1
  end
  leading
end
percentile(counts, perc) click to toggle source
# File lib/spectator/histogram/percentiles.rb, line 405
def self.percentile(counts, perc)
  pcts = [perc]
  results = [0.0]
  percentiles(counts, pcts, results)
  results[0]
end
percentiles(counts, pcts, results) click to toggle source
# File lib/spectator/histogram/percentiles.rb, line 378
def self.percentiles(counts, pcts, results)
  check_perc_args(counts, pcts, results)
  total = counts.inject(0, :+)

  pct_idx = 0
  prev = 0
  prev_p = 0
  prev_b = 0
  (0..length).each do |i|
    nxt = prev + counts[i]
    next_p = 100.0 * nxt / total
    next_b = @bucket_values[i]

    while pct_idx < pcts.length && next_p >= pcts[pct_idx]
      f = (pcts[pct_idx] - prev_p) / (next_p - prev_p)
      results[pct_idx] = f * (next_b - prev_b) + prev_b
      pct_idx += 1
    end

    break if pct_idx >= pcts.length

    prev = nxt
    prev_p = next_p
    prev_b = next_b
  end
end