aboutsummaryrefslogtreecommitdiff
path: root/tests/builder/cache.test.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/builder/cache.test.py')
-rw-r--r--tests/builder/cache.test.py58
1 files changed, 57 insertions, 1 deletions
diff --git a/tests/builder/cache.test.py b/tests/builder/cache.test.py
index 700a8e4..045e8e9 100644
--- a/tests/builder/cache.test.py
+++ b/tests/builder/cache.test.py
@@ -1,8 +1,33 @@
-"""Tests for the per-instance lazy compile cache."""
+"""Tests for the per-instance lazy compile cache — semantics and cold/warm ratio."""
+
+import time
from edify import Pattern, RegexBuilder
+def _hex_number_builder():
+ return (
+ RegexBuilder()
+ .start_of_input()
+ .assert_ahead()
+ .any_of("0x", "0o", "0b")
+ .end()
+ .capture()
+ .any_of("0x", "0o", "0b")
+ .end()
+ .between(1, 16)
+ .any_of_chars("0123456789abcdefABCDEF")
+ .end_of_input()
+ )
+
+
+def _measure_call_wall_clock(action, iterations):
+ start = time.perf_counter()
+ for _ in range(iterations):
+ action()
+ return time.perf_counter() - start
+
+
def test_two_no_kwargs_to_regex_calls_return_the_same_instance():
builder = RegexBuilder().one_or_more().digit()
first = builder.to_regex()
@@ -61,3 +86,34 @@ def test_chain_step_yields_a_fresh_cache_slot():
def test_pattern_also_caches_across_repeat_to_regex_calls():
pattern = Pattern().string("hi")
assert pattern.to_regex() is pattern.to_regex()
+
+
+def test_warm_to_regex_is_at_least_ten_times_cheaper_than_cold_to_regex():
+ warm_iterations = 200
+ cold_iterations = 200
+
+ cold_total = 0.0
+ for _ in range(cold_iterations):
+ builder = _hex_number_builder()
+ cold_start = time.perf_counter()
+ builder.to_regex()
+ cold_total += time.perf_counter() - cold_start
+
+ warm_builder = _hex_number_builder()
+ warm_builder.to_regex()
+ warm_total = _measure_call_wall_clock(warm_builder.to_regex, warm_iterations)
+
+ average_cold = cold_total / cold_iterations
+ average_warm = warm_total / warm_iterations
+
+ assert average_warm * 10 < average_cold, (
+ f"cache ratio too weak: warm={average_warm * 1e6:.2f}µs, "
+ f"cold={average_cold * 1e6:.2f}µs — warm should be < cold / 10."
+ )
+
+
+def test_repeat_to_regex_returns_the_same_regex_instance():
+ warm_builder = _hex_number_builder()
+ first = warm_builder.to_regex()
+ second = warm_builder.to_regex()
+ assert first is second