Skip to main content

jitter/
jitter.rs

1//! Deterministic jitter with a seeded PRNG. Two policies built from the *same*
2//! seed produce the *same* delay sequence — reproducible chaos, ideal for P2P
3//! simulations and consensus tests — while still spreading peers out to avoid a
4//! thundering herd.
5//!
6//! Run with:
7//!
8//! ```text
9//! cargo run --example jitter
10//! ```
11
12use std::time::Duration;
13
14use sisyphus::{BackoffPolicy, ExponentialBackoff, SplitMix64};
15
16fn delays_for_seed(seed: u64) -> Vec<Duration> {
17    // ±50% symmetric jitter around an exponentially growing interval.
18    let mut policy = ExponentialBackoff::new(Duration::from_millis(100), 2.0)
19        .with_jitter(SplitMix64::new(seed), 0.5);
20    (0..6).map(|_| policy.next_delay().unwrap()).collect()
21}
22
23fn main() {
24    let seed = 0xC0FF_EE00;
25
26    let run_a = delays_for_seed(seed);
27    let run_b = delays_for_seed(seed);
28    let run_c = delays_for_seed(seed + 1);
29
30    println!("seed {seed:#x}, run A: {run_a:?}");
31    println!("seed {seed:#x}, run B: {run_b:?}");
32    println!("seed {:#x}, run C: {run_c:?}", seed + 1);
33
34    assert_eq!(run_a, run_b, "same seed must reproduce the same jitter");
35    assert_ne!(run_a, run_c, "different seed should differ");
36
37    println!("\nNominal (no-jitter) intervals would have been: 100, 200, 400, 800, 1600, 3200 ms");
38    println!("Reproducibility verified: same seed -> identical sequence.");
39}