package bitswap import ( "math/rand" "time" "github.com/ipfs/go-ipfs-delay" ) var sharedRNG = rand.New(rand.NewSource(time.Now().UnixNano())) // InternetLatencyDelayGenerator generates three clusters of delays, // typical of the type of peers you would encounter on the interenet. // Given a base delay time T, the wait time generated will be either: // 1. A normalized distribution around the base time // 2. A normalized distribution around the base time plus a "medium" delay // 3. A normalized distribution around the base time plus a "large" delay // The size of the medium & large delays are determined when the generator // is constructed, as well as the relative percentages with which delays fall // into each of the three different clusters, and the standard deviation for // the normalized distribution. // This can be used to generate a number of scenarios typical of latency // distribution among peers on the internet. func InternetLatencyDelayGenerator( mediumDelay time.Duration, largeDelay time.Duration, percentMedium float64, percentLarge float64, std time.Duration, rng *rand.Rand) delay.Generator { if rng == nil { rng = sharedRNG } return &internetLatencyDelayGenerator{ mediumDelay: mediumDelay, largeDelay: largeDelay, percentLarge: percentLarge, percentMedium: percentMedium, std: std, rng: rng, } } type internetLatencyDelayGenerator struct { mediumDelay time.Duration largeDelay time.Duration percentLarge float64 percentMedium float64 std time.Duration rng *rand.Rand } func (d *internetLatencyDelayGenerator) NextWaitTime(t time.Duration) time.Duration { clusterDistribution := d.rng.Float64() baseDelay := time.Duration(d.rng.NormFloat64()*float64(d.std)) + t if clusterDistribution < d.percentLarge { return baseDelay + d.largeDelay } else if clusterDistribution < d.percentMedium+d.percentLarge { return baseDelay + d.mediumDelay } return baseDelay }