Skip to content

test: shave ServiceBrowser first-query delay on loopback#1720

Merged
bdraco merged 1 commit into
python-zeroconf:masterfrom
bluetoothbot:koan/speed-up-browser-first-query
May 18, 2026
Merged

test: shave ServiceBrowser first-query delay on loopback#1720
bdraco merged 1 commit into
python-zeroconf:masterfrom
bluetoothbot:koan/speed-up-browser-first-query

Conversation

@bluetoothbot
Copy link
Copy Markdown
Contributor

@bluetoothbot bluetoothbot commented May 18, 2026

What

Extend the quick_timing test fixture to also shrink
ServiceBrowser's first-query delay from RFC 6762 §5.2's 20–120 ms
window to 1–5 ms on loopback, drop LOOPBACK_FIND_TIMEOUT from
200 → 75 ms, and apply quick_timing to the four
test_integration_with_* tests in tests/services/test_types.py.

Part of #1707.

Why

ServiceBrowser.__init__ schedules its first query at
random.randint(20, 120) ms — 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 matching response — so timeout is a lower bound on
runtime and the in-browser jitter has to fit underneath it.

The four test_types.py integration tests each call find() twice
with LOOPBACK_FIND_TIMEOUT = 0.2 s, so they pay 400 ms of dead
wait 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: extend quick_timing to also
    patch.object(service_browser, "_FIRST_QUERY_DELAY_RANDOM_INTERVAL", (1, 5)).
    The constant is read once at ServiceBrowser.__init__-time and
    passed to QueryScheduler — patching the module attribute before
    any browser is constructed is sufficient.
  • tests/__init__.py: drop LOOPBACK_FIND_TIMEOUT to 0.075 and
    update the comment to note callers MUST use quick_timing.
  • tests/services/test_types.py: add quick_timing to all four
    integration tests (they do not register via probing so the
    _CHECK_TIME/_REGISTER_TIME shaves are no-ops, but the
    browser-delay shave is real).
  • No production changes.

Testing

poetry run pytest --durations=20 --timeout=60 -q tests — 339 passed, 2 skipped.

Slowest-tests deltas (local, single run):

test before after
test_integration_with_listener 0.67 s 0.20 s
test_integration_with_listener_v6_records 0.69 s 0.19 s
test_integration_with_subtype_and_listener 0.68 s 0.19 s
test_integration_with_listener_ipv6 0.69 s 0.20 s
test_async_zeroconf_service_types 0.74 s 0.55 s

Full 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

`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
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.76%. Comparing base (f9e2359) to head (76c31a7).
⚠️ Report is 3 commits behind head on master.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 18, 2026

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing bluetoothbot:koan/speed-up-browser-first-query (76c31a7) with master (f9e2359)1

Open in CodSpeed

Footnotes

  1. No successful run was found on master (65b22cb) during the generation of this report, so f9e2359 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@bdraco bdraco marked this pull request as ready for review May 18, 2026 04:18
@bdraco bdraco merged commit 0ff3c6b into python-zeroconf:master May 18, 2026
37 checks passed
@bluetoothbot bluetoothbot deleted the koan/speed-up-browser-first-query branch May 18, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants