From 8f98d9a51254022c2429b86395bf9ec01b587f17 Mon Sep 17 00:00:00 2001 From: "Geoffrey M. Oxberry" Date: Wed, 20 May 2026 17:54:08 -0700 Subject: [PATCH] feat(payload): adopt Probability for ValueConf::float_probability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change `ValueConf::float_probability` from `f32` to the `Probability` alias of `BoundedProbability<{ f32::to_bits(0.0) }>`. The `try_from` impl enforces the finite + `[0.0, 1.0]` invariant at deserialize time; `ValueConf::new` now takes the validated type directly. (`ValueConf::valid` already had no finite/range check on this field, so nothing is removed there.) The new type threads through `NumValueGenerator`'s `Constant` and `Uniform` variants. At the two comparison sites in `:: generate`, `.get()` extracts the inner `f32` so RNG sequences and bit-exact output are preserved. Verified: `cargo test -p lading-payload` (250 pass). `cargo bench -p lading-payload --bench dogstatsd --baseline pr1` shows ±2-6% swings across all throughput sizes; the unrelated `cache_*` benches in `--bench block` show similar magnitude run-to-run variance, so the delta is noise rather than a real effect. --- lading_payload/src/dogstatsd.rs | 8 ++++---- lading_payload/src/dogstatsd/common.rs | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lading_payload/src/dogstatsd.rs b/lading_payload/src/dogstatsd.rs index 0d42d5e65..eed745059 100644 --- a/lading_payload/src/dogstatsd.rs +++ b/lading_payload/src/dogstatsd.rs @@ -113,15 +113,15 @@ impl Default for MetricWeights { #[serde(deny_unknown_fields)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct ValueConf { - /// Odds out of 256 that the value will be a float and not an integer. - float_probability: f32, + /// Probability that the value will be a float and not an integer. + float_probability: Probability, range: ConfRange, } impl ValueConf { /// Create a new instance of `ValueConf` according to the args #[must_use] - pub fn new(float_probability: f32, range: ConfRange) -> Self { + pub fn new(float_probability: Probability, range: ConfRange) -> Self { Self { float_probability, range, @@ -136,7 +136,7 @@ impl ValueConf { impl Default for ValueConf { fn default() -> Self { Self { - float_probability: 0.5, // 50% + float_probability: Probability::try_new(0.5).expect("0.5 is in [0.0, 1.0]"), range: ConfRange::Inclusive { min: i64::MIN, max: i64::MAX, diff --git a/lading_payload/src/dogstatsd/common.rs b/lading_payload/src/dogstatsd/common.rs index 3ea307946..47bd77088 100644 --- a/lading_payload/src/dogstatsd/common.rs +++ b/lading_payload/src/dogstatsd/common.rs @@ -6,7 +6,7 @@ use rand::{ prelude::Distribution, }; -use crate::{Error, Generator}; +use crate::{Error, Generator, common::config::Probability}; use super::{ConfRange, ValueConf}; @@ -21,12 +21,12 @@ pub enum NumValue { #[derive(Clone, Debug)] pub(crate) enum NumValueGenerator { Constant { - float_probability: f32, + float_probability: Probability, int: i64, float: f64, }, Uniform { - float_probability: f32, + float_probability: Probability, int_distr: Uniform, float_distr: Uniform, }, @@ -67,7 +67,7 @@ impl<'a> Generator<'a> for NumValueGenerator { int, float, } => { - if prob < *float_probability { + if prob < float_probability.get() { Ok(NumValue::Float(*float)) } else { Ok(NumValue::Int(*int)) @@ -78,7 +78,7 @@ impl<'a> Generator<'a> for NumValueGenerator { int_distr, float_distr, } => { - if prob < *float_probability { + if prob < float_probability.get() { Ok(NumValue::Float(float_distr.sample(rng))) } else { Ok(NumValue::Int(int_distr.sample(rng)))