@@ -38,18 +38,26 @@ method generateForIntermediate*(
3838 encodedDelayMs
3939
4040const DefaultMeanDelayMs * = 100
41+ const DefaultNegligibleProb * = 1 e-6
42+ # # Probability below which the tail of the exponential distribution is truncated.
43+ # # Yields a maximum delay of mean * -ln(negligibleProb) ≈ mean * 13.8.
4144
4245type ExponentialDelayStrategy * = ref object of DelayStrategy
4346 # # Recommended strategy: encodes mean delay, samples from exponential distribution.
47+ # # The distribution is truncated at -mean*ln(negligibleProb), discarding the
48+ # # impractically long tail while preserving the mixing properties.
4449 meanDelayMs: uint16
50+ negligibleProb: float64
4551
4652proc new * (
4753 T: typedesc [ExponentialDelayStrategy ],
4854 meanDelayMs: uint16 = DefaultMeanDelayMs ,
4955 rng: ref HmacDrbgContext ,
56+ negligibleProb: float64 = DefaultNegligibleProb ,
5057): T =
5158 doAssert (rng != nil , " random is not set" )
52- T (meanDelayMs: meanDelayMs, rng: rng)
59+ doAssert (negligibleProb > 0.0 and negligibleProb < 1.0 , " negligibleProb must be in (0, 1)" )
60+ T (meanDelayMs: meanDelayMs, rng: rng, negligibleProb: negligibleProb)
5361
5462method generateForEntry * (
5563 self: ExponentialDelayStrategy
@@ -59,11 +67,12 @@ method generateForEntry*(
5967method generateForIntermediate * (
6068 self: ExponentialDelayStrategy , meanDelayMs: uint16
6169): uint16 {.gcsafe , raises : [].} =
62- # # Samples from exponential distribution: delay = -mean * ln(U)
63- # # Fall back to no delay in case of errors
70+ # # Samples from exponential distribution: delay = -mean * ln(U), truncated to
71+ # # -mean*ln(negligibleProb) to discard the impractically long tail.
6472 if meanDelayMs == 0 :
6573 return 0 u16
74+ let maxDelayMs = - float64 (meanDelayMs) * ln (self.negligibleProb)
6675 let randVal = self.rng[].generate (uint64 )
6776 let u = (float64 (randVal) + 1.0 ) / (float64 (high (uint64 )) + 1.0 )
6877 let delay = - float64 (meanDelayMs) * ln (u)
69- min (delay, float64 ( high ( uint16 )) ).uint16
78+ min (delay, maxDelayMs ).uint16
0 commit comments