test: add benchmarks for cache mark-to-expire path (#1780)#1785
Conversation
…xpire Pin the cost of RFC 6762 §10.2 paragraph 2 cache-expiry path (_async_set_created_ttl in-place mutation) so a copy-on-expire follow-up (issue python-zeroconf#1780) has a baseline to measure against.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1785 +/- ##
=======================================
Coverage 99.77% 99.77%
=======================================
Files 33 33
Lines 3536 3536
Branches 498 498
=======================================
Hits 3528 3528
Misses 5 5
Partials 3 3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Merging this PR will not alter performance
Performance Changes
Comparing |
bdraco
left a comment
There was a problem hiding this comment.
This looks wrong. It needs to make sure it only iterates the benchmark once since it will only measure the first clear. And be careful not to measure cost of adding
Rebase with requested adjustmentsBranch StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
PR Review — test: add benchmarks for cache mark-to-expire path (#1780)The three benchmarks have a load-bearing correctness bug that the CodSpeed report itself surfaces: 🔴 Blocking1. all_stale benchmark only measures the first iteration's mutation path (`tests/benchmarks/test_cache_mark_expire.py`, L21-51)This benchmark doesn't measure what its docstring claims. The CodSpeed report on this PR is the smoking gun: Fix: reset cache state before each measured iteration without including setup in the timing. The standard records = [DNSAddress(name, _TYPE_A, _UNIQUE_CLASS, 120, _ipv4_bytes(i), created=now - 5_000) for i in range(1000)]
def _setup():
cache = DNSCache()
cache.async_add_records(records)
return (cache, unique_types, answers, now), {}
benchmark.pedantic(
DNSCache.async_mark_unique_records_older_than_1s_to_expire,
setup=_setup,
rounds=50,
iterations=1,
)This keeps the 2. many_unique_types has the same first-iteration-only problem (`tests/benchmarks/test_cache_mark_expire.py`, L79-123)Same root cause as the first benchmark: the 100 cached PTR records start with 🟢 Suggestions1. Docstring carries narrative that belongs in the PR body (`tests/benchmarks/test_cache_mark_expire.py`, L1-8)Per CLAUDE.md, test docstrings should pin what the test asserts in one sentence — not retell the production-side story. The line-number reference ( Checklist
SummaryThe three benchmarks have a load-bearing correctness bug that the CodSpeed report itself surfaces: To rebase specific severity levels, mention me: Automated review by Kōanf6f4a8e |
Rebase with requested adjustmentsBranch Changes applied
StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
What
Three CodSpeed benchmarks covering
DNSCache.async_mark_unique_records_older_than_1s_to_expire— the RFC 6762 §10.2 paragraph 2 path that today mutates cachedDNSRecordinstances in place via_async_set_created_ttl.Why
Issue #1780 proposes switching from in-place mutation to copy-on-expire so listeners and
ServiceInfoconsumers that hold a reference to a cached record don't see its TTL/created flip out from under them mid-dispatch. The follow-up decision (fix vs. leave as-is) needs a baseline number for the current hot path — these benchmarks supply that.How
test_mark_to_expire_1000_records_all_stale— every cached record triggers the mutate-and-re-add branch (worst case).test_mark_to_expire_1000_records_none_stale— fresh records, scan-only path; the delta to the all-stale case isolates the mutation cost.test_mark_to_expire_many_unique_types— 100 distinct(name, type, class)triplets, one stale record each — mirrors a burst response superseding many RRsets at once.No code changes outside
tests/benchmarks/.Testing
poetry run pytest tests/benchmarks/test_cache_mark_expire.py -v— 3 passed.Quality Report
Changes: 1 file changed, 123 insertions(+)
Code scan: clean
Tests: passed (4 PASSED)
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline