diff --git a/evalharness/model/pool.py b/evalharness/model/pool.py index cbac67b..599633a 100644 --- a/evalharness/model/pool.py +++ b/evalharness/model/pool.py @@ -312,7 +312,7 @@ class AdaptiveGate: # not enough evidence yet at this level: keep measuring. # need = max(MIN_OK, level): rate noise shrinks only with # samples proportional to the concurrency being judged - need_ok = max(self.MIN_OK, lvl) + need_ok = max(self.MIN_OK, lvl * 2) if self._level_ok < need_ok and dt < self.MAX_AT_LEVEL_S: return # zero completions in MAX_AT_LEVEL_S: hang or overloaded -> hold @@ -325,15 +325,20 @@ class AdaptiveGate: if self._mode == 'probe': self.stats['probe'] += 1 - improved = prev_rate is None or rate > prev_rate * self.GAIN_EPS - if improved and lvl < self.HI: + # continue while NOT WORSE (>= 0.9x): with heterogeneous + # request lengths (lbv2: 4k..2M-token docs) completion-rate + # noise dwarfs a 10% gain threshold, and demanding strict + # improvement bisected [1,2]->1 on the first plateau. + # Only CLEAR degradation (<0.9x) means past the knee. + ok = prev_rate is None or rate >= prev_rate * 0.9 + if ok and lvl < self.HI: self._bis = (lvl, min(lvl * 2, self.HI)) # remember bounds self.limit = float(min(lvl * 2, self.HI)) self.stats['ramp_demand'] += 1 self._push_limit() self._enter_level() - elif not improved: - # throughput plateaued: knee is between prev_lvl and lvl + elif not ok: + # throughput CLEARLY degraded: knee is in (prev_lvl, lvl] self._mode = 'bisect' self._bis = (prev_lvl or max(1, lvl // 2), lvl) self._good_rate = prev_rate or rate @@ -350,13 +355,24 @@ class AdaptiveGate: self._enter_level() else: self._enter_level('steady') # hit HI with gains: stay + elif self._mode == 'steady': + # capacity estimates are noisy: periodically re-probe upward + self._steady_ticks = getattr(self, '_steady_ticks', 0) + 1 + if self._steady_ticks >= 12: # ~60s at PROBE_S=5 + self._steady_ticks = 0 + self._mode = 'probe' + self._prev = (lvl, rate) + # try one level up, not a full double, from settled state + self.limit = float(min(lvl + 1, self.HI)) + self._push_limit() + self._enter_level() + return elif self._mode == 'bisect': lo, hi = self._bis - if rate > self._good_rate * self.GAIN_EPS: - lo = lvl # still improving: knee is higher - self._good_rate = rate + if rate >= self._good_rate * 0.9: + lo = lvl # not worse here: knee is at/above else: - hi = lvl # no gain: knee is lower + hi = lvl # clearly worse: knee is below self._bis = (lo, hi) if hi - lo <= 1: self.limit = float(lo)