number of items tracked by this bucket.
timestamp of the most recent item tracked by this bucket.
ExpHist guarantees that the returned guess will be within
epsilon
relative error of the true count across a sliding
window of size windowSize
.
ExpHist guarantees that the returned guess will be within
epsilon
relative error of the true count across a sliding
window of size windowSize
.
relative error, from [0, 0.5]
number of time ticks to track
Value class wrapper around timestamps (>= 0) used by each bucket.
The paper that introduces the exponential histogram proves that,
given a positive number l
, every integer s can be uniquely
represented as the sum of
The paper that introduces the exponential histogram proves that,
given a positive number l
, every integer s can be uniquely
represented as the sum of
(l or (l + 1)) * 2i + (# from 1 to (l + 1)) 2j
for i = (0 to j - 1), given some j.
The paper calls this the "l-canonical" representation of s.
It turns out that if you follow the exponential histogram bucket-merging algorithm, you end up with the invariant that the number of buckets with size 2^i exactly matches that power of 2's coefficient in s's l-canonical representation.
Put another way - only sequences of buckets with sizes matching the l-canonical representation of some number s are valid exponential histograms.
(We use this idea in ExpHist.rebucket
to take a sequence of
buckets of any size and rebucket them into a sequence where the
above invariant holds.)
This is huge. This means that you can implement addAll(newBuckets)
by
- calculating newS = s + delta contributed by newBuckets - generating the l-canonical sequence of bucket sizes for newS - rebucketing newBuckets ++ oldBuckets into those bucket sizes
The resulting sequence of buckets is a valid exponential histogram.
Returns an empty instance with the supplied Config.
Returns an instance directly from a number i
.
Returns an instance directly from a number i
. All buckets in
the returned ExpHist will have the same timestamp, equal to
ts
.