ClosedLoop

class ClosedLoop(client: Client, mix: Mix, keysOf: (Int) -> KeyChooser, targets: List<URI>, startConcurrency: Int, maxConcurrency: Int, warmUpSeconds: Int, stepSeconds: Int, minGain: Double = DEFAULT_MIN_GAIN, maxErrorRate: Double = DEFAULT_MAX_ERROR_RATE, sweep: Boolean = false, growth: Int = 2, concurrencies: List<Int>? = null, failAfterSeconds: Int? = null, cpuSeconds: () -> Double = ::ownCpuSeconds, log: (String) -> Unit = {})

The closed-loop saturation finder: concurrency workers each send an operation and send the next when it completes, for a step of stepSeconds after warmUpSeconds; the concurrency grows growth times a step from startConcurrency (doubles by default; 4 sweeps 1 to 1,024 in six steps instead of eleven) until the throughput stops growing by minGain two steps in a row (unless it sweeps), errors pass maxErrorRate, or maxConcurrency is reached; or, with concurrencies, exactly those steps in that order, up to the first whose errors pass maxErrorRate. The highest throughput seen is the saturation point the open-loop runs take their 50% and 80% rates from. A closed loop's latencies understate a saturated server's (coordinated omission): they are recorded only to show where the knee is, never as a result.

With failAfterSeconds, a failing step ends early: once it has measured that long, its errors so far pass maxErrorRate and its throughput so far is below an earlier step's, it stops (stopsEarly). That is long enough to record what failed, and such a step is never the saturation point, so the point is measured as long as before.

Constructors

Link copied to clipboard
constructor(client: Client, mix: Mix, keysOf: (Int) -> KeyChooser, targets: List<URI>, startConcurrency: Int, maxConcurrency: Int, warmUpSeconds: Int, stepSeconds: Int, minGain: Double = DEFAULT_MIN_GAIN, maxErrorRate: Double = DEFAULT_MAX_ERROR_RATE, sweep: Boolean = false, growth: Int = 2, concurrencies: List<Int>? = null, failAfterSeconds: Int? = null, cpuSeconds: () -> Double = ::ownCpuSeconds, log: (String) -> Unit = {})

Types

Link copied to clipboard
object Companion
Link copied to clipboard
data class Step(val concurrency: Int, val ok: Long, val errors: Map<String, Long>, val seconds: Int, val latency: Histogram, val generatorCores: Double = 0.0, val sentOk: Long = 0, val sentFailed: Long = 0)

One step: its concurrency, throughput and latencies, and the cores the load generator used in its measured phase, so a step the generator could not drive is told from one the servers could not keep up with; and every operation it sent, its warm-up's too, that reached its completion point (sentOk) or failed (sentFailed).

Functions

Link copied to clipboard