Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added variable latency delay, normal and uniform based #2871

Merged
merged 1 commit into from
Jun 20, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions thirdparty/delay/delay.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package delay

import (
"math/rand"
"sync"
"time"
)

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

// Delay makes it easy to add (threadsafe) configurable delays to other
// objects.
type D interface {
Expand All @@ -23,8 +26,6 @@ type delay struct {
t time.Duration
}

// TODO func Variable(time.Duration) D returns a delay with probablistic latency

func (d *delay) Set(t time.Duration) time.Duration {
d.l.Lock()
defer d.l.Unlock()
Expand All @@ -44,3 +45,61 @@ func (d *delay) Get() time.Duration {
defer d.l.Unlock()
return d.t
}

// VariableNormal is a delay following a normal distribution
// Notice that to implement the D interface Set can only change the mean delay
// the standard deviation is set only at initialization
func VariableNormal(t, std time.Duration, rng *rand.Rand) D {
if rng == nil {
rng = sharedRNG
}

v := &variableNormal{
std: std,
rng: rng,
}
v.t = t
return v
}

type variableNormal struct {
delay
std time.Duration
rng *rand.Rand
}

func (d *variableNormal) Wait() {
d.l.RLock()
defer d.l.RUnlock()
randomDelay := time.Duration(d.rng.NormFloat64() * float64(d.std))
time.Sleep(randomDelay + d.t)
}

// VariableUniform is a delay following a uniform distribution
// Notice that to implement the D interface Set can only change the minimum delay
// the delta is set only at initialization
func VariableUniform(t, d time.Duration, rng *rand.Rand) D {
if rng == nil {
rng = sharedRNG
}

v := &variableUniform{
d: d,
rng: rng,
}
v.t = t
return v
}

type variableUniform struct {
delay
d time.Duration // max delta
rng *rand.Rand
}

func (d *variableUniform) Wait() {
d.l.RLock()
defer d.l.RUnlock()
randomDelay := time.Duration(d.rng.Float64() * float64(d.d))
time.Sleep(randomDelay + d.t)
}