internet_latency_delay_generator.go 1.95 KB
Newer Older
1 2 3 4 5 6
package bitswap

import (
	"math/rand"
	"time"

7
	delay "gitlab.dms3.io/dms3/go-dms3-delay"
8 9 10 11 12
)

var sharedRNG = rand.New(rand.NewSource(time.Now().UnixNano()))

// InternetLatencyDelayGenerator generates three clusters of delays,
13
// typical of the type of peers you would encounter on the interenet.
14 15 16 17 18 19 20
// 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
21
// the normalized distribution.
22
// This can be used to generate a number of scenarios typical of latency
23
// distribution among peers on the internet.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
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
}