fix: slow-down point ignores a one-step latency blip

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev 23eab4cf0d65f30838991ce904f10b8b550cddf7 parent c2b9263
2 files changed, +26 −5
  • harness/harness_test.go +7 −0
  • harness/sweep.go +19 −5
diff --git a/harness/harness_test.go b/harness/harness_test.go
index 57304b8..0b43b70 100644
--- a/harness/harness_test.go
+++ b/harness/harness_test.go
@@ -301,3 +301,10 @@ func TestSweepStopsOnErrorsOrFlatThroughput(t *testing.T) {
t.Fatal("one flat step then growth: keep going")
}
}
+
+func TestKneeIgnoresAOneStepBlip(t *testing.T) {
+ sweep := []LoadResult{lr(1, 58, 29, 0), lr(2, 108, 38, 0), lr(4, 98, 66, 0), lr(8, 184, 77, 0), lr(16, 314, 97, 0), lr(32, 325, 294, 0), lr(64, 324, 640, 0)}
+ if k := Knee(sweep); !k.Found || k.Concurrency != 16 || k.PeakRPS != 325 {
+ t.Fatalf("got %+v, want 16: the fewest connections from which no more load adds 10%%", k)
+ }
+}
diff --git a/harness/sweep.go b/harness/sweep.go
index 1075202..c2aefc9 100644
--- a/harness/sweep.go
+++ b/harness/sweep.go
@@ -19,17 +19,31 @@ type KneeResult struct {
MaxTested int
}
-// Knee finds the first doubling that raised throughput by less than 10%:
-// the app slows down past the level before it.
+// Knee finds where the app slows down: the fewest connections from which
+// no further load in the sweep raised throughput by 10% or more. A single
+// noisy step can't end the search early, because later growth resets it.
func Knee(sweep []LoadResult) KneeResult {
var k KneeResult
- for i, r := range sweep {
+ for _, r := range sweep {
if r.RPS > k.PeakRPS {
k.PeakRPS = r.RPS
}
k.MaxTested = r.Concurrency
- if !k.Found && i > 0 && r.RPS < sweep[i-1].RPS*flatGain {
- k.Found, k.Concurrency, k.P50Ms = true, sweep[i-1].Concurrency, sweep[i-1].P50Ms
+ }
+ for i, r := range sweep {
+ if i == len(sweep)-1 {
+ break
+ }
+ gains := false
+ for _, later := range sweep[i+1:] {
+ if later.RPS >= r.RPS*flatGain {
+ gains = true
+ break
+ }
+ }
+ if !gains {
+ k.Found, k.Concurrency, k.P50Ms = true, r.Concurrency, r.P50Ms
+ break
}
}
return k