-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathtest_cache_bound.py
More file actions
68 lines (53 loc) · 2.23 KB
/
test_cache_bound.py
File metadata and controls
68 lines (53 loc) · 2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"""Benchmark for the DNSCache record-count bound + overflow eviction."""
from __future__ import annotations
from collections.abc import Iterator
from itertools import count
from pytest_codspeed import BenchmarkFixture
from zeroconf import DNSAddress, DNSCache, current_time_millis
from zeroconf.const import _CLASS_IN, _MAX_CACHE_RECORDS, _TYPE_A
def _make_records(count_: int, now: float, prefix: str = "bench") -> list[DNSAddress]:
return [
DNSAddress(
f"{prefix}-{i}.local.",
_TYPE_A,
_CLASS_IN,
120,
bytes(((i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF)),
created=now + i,
)
for i in range(count_)
]
def _unbounded_records(now: float, prefix: str = "evict") -> Iterator[DNSAddress]:
"""Unbounded generator of unique-name DNSAddress records."""
for i in count():
yield DNSAddress(
f"{prefix}-{i}.local.",
_TYPE_A,
_CLASS_IN,
120,
bytes(((i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF)),
created=now + i,
)
def test_cache_add_below_cap(benchmark: BenchmarkFixture) -> None:
"""Adding records while the cache is well below the cap (no eviction)."""
now = current_time_millis()
records = _make_records(1000, now)
@benchmark
def _add() -> None:
cache = DNSCache()
cache.async_add_records(records)
def test_cache_add_at_cap_evicts(benchmark: BenchmarkFixture) -> None:
"""Steady-state add at the cap: every measured insert forces one eviction.
Pre-fills the cache to ``_MAX_CACHE_RECORDS`` outside the timed body so
only the eviction-path adds are measured. Each benchmark iteration
pulls one fresh unique record from an unbounded generator, keeping the
cache permanently at the cap. The generator avoids the iteration-count
cap that a pre-built pool would impose for very fast operations.
"""
now = current_time_millis()
cache = DNSCache()
cache.async_add_records(_make_records(_MAX_CACHE_RECORDS, now, prefix="fill"))
pool = _unbounded_records(now + _MAX_CACHE_RECORDS)
@benchmark
def _evict_one() -> None:
cache.async_add_records([next(pool)])