Skip to content

Commit bf44790

Browse files
committed
fix(sender): remove busy-wait between reply arrival and next probe
The session sender loop only blocked in the select immediately after sending a probe. When the reflected reply arrived, that select returned after one RTT, the reply was drained at the top of the loop, and the loop then spun on the zero-timeout select until the next 1-second deadline: a pure busy-wait costing (interval - RTT) of one core per interval, i.e. roughly one full core per sender session at the default probe rate. Move the wait out of the send branch: after draining replies and the endtime check, block on select until the next probe deadline, or until endtime once all probes have been sent. A reply still wakes the select early and is drained normally, so timing, sequencing, statistics and log output are unchanged. Loopback validation (10 probes, -i 1000, local responder): original: wall 9.07s, CPU 9.06s (100% of a core) patched: wall 9.09s, CPU 0.07s (~1%) 0.0% loss, probes exactly 1s apart, reply log lines unchanged. Full test suite: 12 passed.
1 parent 885b986 commit bf44790

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

src/twampy/__main__.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,13 +349,22 @@ def run(self):
349349
log.info("Sent to %s [sseq=%d]", self.remote_addr, idx)
350350

351351
idx = idx + 1
352-
if schedule > t1:
353-
r, w, e = select.select([self.socket], [], [], schedule - t1)
354352

355353
if t1 > endtime:
356354
log.info("Receive timeout for last packet (don't wait anymore)")
357355
self.running = False
358356

357+
# Block until the next probe deadline (or wake early when a reply
358+
# arrives). Waiting only right after a send is not enough: the
359+
# arriving reply makes that select return after one RTT, and the
360+
# loop then spins on the zero-timeout select above until the next
361+
# deadline, burning (interval - RTT) of CPU every interval.
362+
if self.running:
363+
wait_until = schedule if idx < self.count else endtime
364+
timeout = wait_until - now()
365+
if timeout > 0:
366+
select.select([self.socket], [], [], timeout)
367+
359368
self.stats.dump(idx)
360369

361370

0 commit comments

Comments
 (0)