test: shave ServiceBrowser first-query delay on loopback#1720
Merged
bdraco merged 1 commit intoMay 18, 2026
Merged
Conversation
`ServiceBrowser` waits `random.randint(20, 120)` ms before its first query — RFC 6762 §5.2 thundering-herd avoidance for real networks, pure overhead on 127.0.0.1. Every browser-using test pays it, and `ZeroconfServiceTypes.find()` adds it on top of `time.sleep(timeout)` because find() doesn't short-circuit on the first response. Extend `quick_timing` to also patch `_FIRST_QUERY_DELAY_RANDOM_INTERVAL` to (1, 5) ms, drop `LOOPBACK_FIND_TIMEOUT` from 200 → 75 ms (still ~7x headroom over the ~10 ms response latency on loopback), and apply `quick_timing` to the four `test_integration_with_*` tests in tests/services/test_types.py. Numbers on a local run: test_integration_with_listener 0.67s → 0.20s test_integration_with_listener_v6_records 0.69s → 0.19s test_integration_with_subtype_and_listener 0.68s → 0.19s test_integration_with_listener_ipv6 0.69s → 0.20s test_async_zeroconf_service_types 0.74s → 0.55s Full suite: 48.78s → 42.94s (-12%). Part of python-zeroconf#1707.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1720 +/- ##
=======================================
Coverage 99.76% 99.76%
=======================================
Files 33 33
Lines 3428 3428
Branches 472 472
=======================================
Hits 3420 3420
Misses 5 5
Partials 3 3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
bdraco
approved these changes
May 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Extend the
quick_timingtest fixture to also shrinkServiceBrowser's first-query delay from RFC 6762 §5.2's 20–120 mswindow to 1–5 ms on loopback, drop
LOOPBACK_FIND_TIMEOUTfrom200 → 75 ms, and apply
quick_timingto the fourtest_integration_with_*tests intests/services/test_types.py.Part of #1707.
Why
ServiceBrowser.__init__schedules its first query atrandom.randint(20, 120)ms — thundering-herd avoidance for realnetworks, pure overhead on 127.0.0.1. Every browser-using test pays
it, and
ZeroconfServiceTypes.find()adds it on top oftime.sleep(timeout)becausefind()doesn't short-circuit onthe first matching response — so
timeoutis a lower bound onruntime and the in-browser jitter has to fit underneath it.
The four
test_types.pyintegration tests each callfind()twicewith
LOOPBACK_FIND_TIMEOUT = 0.2 s, so they pay 400 ms of deadwait alone. With first-query delay at ≤5 ms the response lands
inside ~10 ms; 75 ms leaves ~7× headroom while halving the floor.
How
tests/conftest.py: extendquick_timingto alsopatch.object(service_browser, "_FIRST_QUERY_DELAY_RANDOM_INTERVAL", (1, 5)).The constant is read once at
ServiceBrowser.__init__-time andpassed to
QueryScheduler— patching the module attribute beforeany browser is constructed is sufficient.
tests/__init__.py: dropLOOPBACK_FIND_TIMEOUTto0.075andupdate the comment to note callers MUST use
quick_timing.tests/services/test_types.py: addquick_timingto all fourintegration tests (they do not register via probing so the
_CHECK_TIME/_REGISTER_TIMEshaves are no-ops, but thebrowser-delay shave is real).
Testing
poetry run pytest --durations=20 --timeout=60 -q tests— 339 passed, 2 skipped.Slowest-tests deltas (local, single run):
test_integration_with_listenertest_integration_with_listener_v6_recordstest_integration_with_subtype_and_listenertest_integration_with_listener_ipv6test_async_zeroconf_service_typesFull suite: 48.78 s → 42.94 s (-12%).
Quality Report
Changes: 3 files changed, 18 insertions(+), 12 deletions(-)
Code scan: clean
Tests: passed (4 PASSED)
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline