Skip to content

Commit e518479

Browse files
authored
Merge pull request #220 from derek73/fix/flaky-cache-timing-test
Fix flaky cache-timing test with a ratio-based assertion
2 parents 14b7098 + 7a51c01 commit e518479

1 file changed

Lines changed: 20 additions & 13 deletions

File tree

tests/test_constants.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,11 @@ class SuffixesPrefixesTitlesPerformanceTests(HumanNameTestBase):
492492
493493
This library is commonly used to parse large batches of names, so
494494
suffixes_prefixes_titles must remain cached. Without the cache, each call
495-
rebuilds the union from ~700 strings (~50-100 µs); with it, repeated access
496-
is ~1000x faster. This test asserts that 10 000 repeated calls complete
497-
well within the time a single uncached union build would take.
495+
rebuilds the union from ~700 strings; with it, repeated access is
496+
orders of magnitude faster. Rather than compare against a fixed
497+
wall-clock budget (which flakes on slower/noisier CI runners), this
498+
measures the uncached build cost on the same machine and asserts cached
499+
access is much faster than that baseline.
498500
"""
499501

500502
def test_repeated_access_is_cached(self) -> None:
@@ -503,15 +505,20 @@ def test_repeated_access_is_cached(self) -> None:
503505
second = c.suffixes_prefixes_titles
504506
assert first is second, "suffixes_prefixes_titles should return the same cached object on repeated access"
505507

508+
# Baseline: cost of an uncached build, measured via fresh instances
509+
# (each instance's first access rebuilds the union) on this machine.
510+
m = 50
511+
uncached_per_call = timeit.timeit(lambda: Constants().suffixes_prefixes_titles, number=m) / m
512+
506513
n = 10_000
507-
elapsed = timeit.timeit(lambda: c.suffixes_prefixes_titles, number=n)
508-
509-
# One uncached union build over ~700 strings takes ~50-100 µs on any
510-
# modern machine. If caching is broken, 10 000 calls would take
511-
# seconds; with caching they finish in well under 10 ms total.
512-
limit = 0.010 # 10 ms = 1 µs/call average
513-
assert elapsed < limit, (
514-
f"suffixes_prefixes_titles appears uncached: {n} calls took "
515-
f"{elapsed * 1000:.1f} ms (limit {limit * 1000:.0f} ms). "
516-
"Was _pst caching removed?"
514+
cached_per_call = timeit.timeit(lambda: c.suffixes_prefixes_titles, number=n) / n
515+
516+
# If caching is broken, cached_per_call would be roughly the same as
517+
# uncached_per_call. With caching intact it should be at least an
518+
# order of magnitude faster.
519+
limit = uncached_per_call / 10
520+
assert cached_per_call < limit, (
521+
f"suffixes_prefixes_titles appears uncached: cached access averaged "
522+
f"{cached_per_call * 1e6:.1f} us/call vs an uncached build cost of "
523+
f"{uncached_per_call * 1e6:.1f} us/call. Was _pst caching removed?"
517524
)

0 commit comments

Comments
 (0)