summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Hawkins <[email protected]>2022-11-07 18:29:03 -0500
committerWill Hawkins <[email protected]>2022-11-07 18:32:01 -0500
commit86f822c37f8fcc70d3a1085f4769ec58752f50c1 (patch)
tree5f1a1e070590d5669b0c36eab1faaba99e4478af
parent715e074b068d98bdf466ed33e08a1f54b31c3d44 (diff)
[Feature] Redefine stability
Stability (in rev3) is based on whether the standard deviations of the measurements are within a certain percentage of the average. This commit adds that functionality.
-rw-r--r--constants/constants.go26
-rw-r--r--stabilizer/rev3.go50
2 files changed, 56 insertions, 20 deletions
diff --git a/constants/constants.go b/constants/constants.go
index c4f2c20..6934459 100644
--- a/constants/constants.go
+++ b/constants/constants.go
@@ -17,17 +17,21 @@ package constants
import "time"
var (
- // The initial number of connections on a LBC.
- StartingNumberOfLoadGeneratingConnections uint64 = 4
- // The number of intervals for which to account in a moving-average
- // calculation.
- MovingAverageIntervalCount int = 4
- // The number of intervals across which to consider a moving average stable.
- MovingAverageStabilitySpan uint64 = 4
- // The number of connections to add to a LBC when unsaturated.
- AdditiveNumberOfLoadGeneratingConnections uint64 = 4
- // The cutoff of the percent difference that defines instability.
- InstabilityDelta float64 = 5
+ // The initial number of load-generating connections when attempting to saturate the network.
+ StartingNumberOfLoadGeneratingConnections uint64 = 1
+ // The number of load-generating connections to add at each interval while attempting to
+ // saturate the network.
+ AdditiveNumberOfLoadGeneratingConnections uint64 = 1
+
+ // The number of previous instantaneous measurements to consider when generating the so-called
+ // instantaneous moving averages of a measurement.
+ InstantaneousThroughputMeasurementCount int = 4
+ InstantaneousProbeMeasurementCount int = 1
+ // The number of instantaneous moving averages to consider when determining stability.
+ InstantaneousMovingAverageCount int = 4
+ // The standard deviation cutoff used to determine stability among the K preceding moving averages
+ // of a measurement (as a percentage of the mean).
+ StabilityStandardDeviation float64 = 5.0
// The amount of time that the client will cooldown if it is in debug mode.
CooldownPeriod time.Duration = 4 * time.Second
diff --git a/stabilizer/rev3.go b/stabilizer/rev3.go
index e81fc76..2e29626 100644
--- a/stabilizer/rev3.go
+++ b/stabilizer/rev3.go
@@ -40,8 +40,14 @@ func NewProbeStabilizer(i int, k int, s float64, debugLevel debug.DebugLevel, de
func (r3 *ProbeStabilizer) AddMeasurement(measurement rpm.ProbeDataPoint) {
r3.m.Lock()
defer r3.m.Unlock()
- // Add this instantaneous measurement to the mix of the I previous instantaneous measurements.
- r3.instantaneousMeasurements.AddElement(measurement.Duration.Seconds())
+
+ // There may be more than one round trip accumulated together. If that is the case,
+ // we will blow them apart in to three separate measurements and each one will just
+ // be 1 / measurement.RoundTripCount of the total length.
+ for range utilities.Iota(0, int(measurement.RoundTripCount)) {
+ // Add this instantaneous measurement to the mix of the I previous instantaneous measurements.
+ r3.instantaneousMeasurements.AddElement(measurement.Duration.Seconds() / float64(measurement.RoundTripCount))
+ }
// Calculate the moving average of the I previous instantaneous measurements and add it to
// the mix of K previous moving averages.
r3.movingAverages.AddElement(r3.instantaneousMeasurements.CalculateAverage())
@@ -58,14 +64,27 @@ func (r3 *ProbeStabilizer) AddMeasurement(measurement rpm.ProbeDataPoint) {
func (r3 *ProbeStabilizer) IsStable() bool {
// calculate whether the standard deviation of the K previous moving averages falls below S.
- islt, stddev := r3.movingAverages.StandardDeviationLessThan(r3.stabilityStandardDeviation)
+ isvalid, stddev := r3.movingAverages.StandardDeviation()
+
+ if !isvalid {
+ // If there are not enough values in the series to be able to calculate a
+ // standard deviation, then we know that we are not yet stable. Vamoose.
+ return false
+ }
+
+ // Stability is determined by whether or not the standard deviation of the values
+ // is within 5% of the average.
+ stabilityCutoff := r3.movingAverages.CalculateAverage() * (r3.stabilityStandardDeviation / 100.0)
+ isStable := stddev <= stabilityCutoff
if debug.IsDebug(r3.dbgLevel) {
fmt.Printf(
- "%s: Standard Deviation: %f s; Is Normally Distributed? %v).\n",
+ "%s: Is Stable? %v; Standard Deviation: %f s; Is Normally Distributed? %v; Standard Deviation Cutoff: %v s).\n",
r3.dbgConfig.String(),
+ isStable,
stddev,
r3.movingAverages.IsNormallyDistributed(),
+ stabilityCutoff,
)
fmt.Printf("%s: Values: ", r3.dbgConfig.String())
for _, v := range r3.movingAverages.Values() {
@@ -73,7 +92,8 @@ func (r3 *ProbeStabilizer) IsStable() bool {
}
fmt.Printf("\n")
}
- return islt
+
+ return isStable
}
func NewThroughputStabilizer(i int, k int, s float64, debugLevel debug.DebugLevel, debug *debug.DebugWithPrefix) ThroughputStabilizer {
@@ -104,15 +124,27 @@ func (r3 *ThroughputStabilizer) AddMeasurement(measurement rpm.ThroughputDataPoi
}
func (r3 *ThroughputStabilizer) IsStable() bool {
- // calculate whether the standard deviation of the K previous moving averages falls below S.
- islt, stddev := r3.movingAverages.StandardDeviationLessThan(r3.stabilityStandardDeviation)
+ isvalid, stddev := r3.movingAverages.StandardDeviation()
+
+ if !isvalid {
+ // If there are not enough values in the series to be able to calculate a
+ // standard deviation, then we know that we are not yet stable. Vamoose.
+ return false
+ }
+
+ // Stability is determined by whether or not the standard deviation of the values
+ // is within 5% of the average.
+ stabilityCutoff := r3.movingAverages.CalculateAverage() * (r3.stabilityStandardDeviation / 100.0)
+ isStable := stddev <= stabilityCutoff
if debug.IsDebug(r3.dbgLevel) {
fmt.Printf(
- "%s: Standard Deviation: %f Mbps; Is Normally Distributed? %v).\n",
+ "%s: Is Stable? %v; Standard Deviation: %f Mbps; Is Normally Distributed? %v; Standard Deviation Cutoff: %v Mbps).\n",
r3.dbgConfig.String(),
+ isStable,
stddev,
r3.movingAverages.IsNormallyDistributed(),
+ stabilityCutoff,
)
fmt.Printf("%s: Values: ", r3.dbgConfig.String())
for _, v := range r3.movingAverages.Values() {
@@ -120,5 +152,5 @@ func (r3 *ThroughputStabilizer) IsStable() bool {
}
fmt.Printf("\n")
}
- return islt
+ return isStable
}