Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog.d/expand-internal-histogram-precision.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Increased the number of buckets in internal histograms to reduce the smallest
bucket down to approximately 0.000244 (2.0^-12). Since this shifts all the
bucket values out, it may break VRL scripts that rely on the previous values.

authors: bruceg
52 changes: 29 additions & 23 deletions lib/vector-core/src/metrics/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ impl<K> Storage<K> for VectorStorage {

#[derive(Debug)]
pub(super) struct Histogram {
buckets: Box<[(f64, AtomicU32); 20]>,
buckets: Box<[(f64, AtomicU32); 26]>,
count: AtomicU64,
sum: AtomicF64,
}

impl Histogram {
const MIN_BUCKET: f64 = 0.015_625; // (-6_f64).exp2() is not const yet
const MIN_BUCKET_EXP: f64 = -6.0;
const BUCKETS: usize = 20;
const MIN_BUCKET: f64 = 1.0 / (1 << 12) as f64; // f64::powi() is not const yet
const MIN_BUCKET_EXP: f64 = -12.0;
const BUCKETS: usize = 26;

pub(crate) fn new() -> Self {
// Box to avoid having this large array inline to the structure, blowing
Expand All @@ -52,25 +52,31 @@ impl Histogram {
// long-tail. This also lets us find the right bucket to record into using simple
// constant-time math operations instead of a loop-and-compare construct.
let buckets = Box::new([
((-6_f64).exp2(), AtomicU32::new(0)),
((-5_f64).exp2(), AtomicU32::new(0)),
((-4_f64).exp2(), AtomicU32::new(0)),
((-3_f64).exp2(), AtomicU32::new(0)),
((-2_f64).exp2(), AtomicU32::new(0)),
((-1_f64).exp2(), AtomicU32::new(0)),
(0_f64.exp2(), AtomicU32::new(0)),
(1_f64.exp2(), AtomicU32::new(0)),
(2_f64.exp2(), AtomicU32::new(0)),
(3_f64.exp2(), AtomicU32::new(0)),
(4_f64.exp2(), AtomicU32::new(0)),
(5_f64.exp2(), AtomicU32::new(0)),
(6_f64.exp2(), AtomicU32::new(0)),
(7_f64.exp2(), AtomicU32::new(0)),
(8_f64.exp2(), AtomicU32::new(0)),
(9_f64.exp2(), AtomicU32::new(0)),
(10_f64.exp2(), AtomicU32::new(0)),
(11_f64.exp2(), AtomicU32::new(0)),
(12_f64.exp2(), AtomicU32::new(0)),
(2.0f64.powi(-12), AtomicU32::new(0)),
(2.0f64.powi(-11), AtomicU32::new(0)),
(2.0f64.powi(-10), AtomicU32::new(0)),
(2.0f64.powi(-9), AtomicU32::new(0)),
(2.0f64.powi(-8), AtomicU32::new(0)),
(2.0f64.powi(-7), AtomicU32::new(0)),
(2.0f64.powi(-6), AtomicU32::new(0)),
(2.0f64.powi(-5), AtomicU32::new(0)),
(2.0f64.powi(-4), AtomicU32::new(0)),
(2.0f64.powi(-3), AtomicU32::new(0)),
(2.0f64.powi(-2), AtomicU32::new(0)),
(2.0f64.powi(-1), AtomicU32::new(0)),
(2.0f64.powi(0), AtomicU32::new(0)),
(2.0f64.powi(1), AtomicU32::new(0)),
(2.0f64.powi(2), AtomicU32::new(0)),
(2.0f64.powi(3), AtomicU32::new(0)),
(2.0f64.powi(4), AtomicU32::new(0)),
(2.0f64.powi(5), AtomicU32::new(0)),
(2.0f64.powi(6), AtomicU32::new(0)),
(2.0f64.powi(7), AtomicU32::new(0)),
(2.0f64.powi(8), AtomicU32::new(0)),
(2.0f64.powi(9), AtomicU32::new(0)),
(2.0f64.powi(10), AtomicU32::new(0)),
(2.0f64.powi(11), AtomicU32::new(0)),
(2.0f64.powi(12), AtomicU32::new(0)),
(f64::INFINITY, AtomicU32::new(0)),
]);
Self {
Expand Down
6 changes: 3 additions & 3 deletions src/sources/internal_metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ mod tests {
// [`metrics::handle::Histogram::new`] are hard-coded. If this
// check fails you might look there and see if we've allowed
// users to set their own bucket widths.
assert_eq!(buckets[9].count, 2);
assert_eq!(buckets[15].count, 2);
assert_eq!(*count, 2);
assert_eq!(*sum, 11.0);
}
Expand All @@ -273,8 +273,8 @@ mod tests {
// [`metrics::handle::Histogram::new`] are hard-coded. If this
// check fails you might look there and see if we've allowed
// users to set their own bucket widths.
assert_eq!(buckets[9].count, 1);
assert_eq!(buckets[10].count, 1);
assert_eq!(buckets[15].count, 1);
assert_eq!(buckets[16].count, 1);
assert_eq!(*count, 2);
assert_eq!(*sum, 16.1);
}
Expand Down
Loading