Skip to content

Commit cb2f077

Browse files
committed
test(compile): accept a delta compile's fresh analysis in the same-runner edit ratio
A delta compile analyses only the models it reruns, without the analysis cache, so the ratio script's cache precondition rejected head's one-model edit as an uncached compile. Each run now records how many models its analysis counters account for. An edit run that analysed fewer models than the project has is a delta, and passes when it analysed at least one model afresh. Full compiles keep the existing checks, so a bypassing full compile is still rejected.
1 parent 160031e commit cb2f077

5 files changed

Lines changed: 75 additions & 5 deletions

File tree

‎scripts/compile_performance_ratio/_helpers/measure.py‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from scripts.cold_compile_performance._helpers.dense_project import write_dense_compile_project
1818
from scripts.compile_performance_ratio._helpers.edit import apply_one_model_edit
1919
from scripts.compile_performance_ratio.constants import (
20+
ANALYSED_MODEL_COUNTERS,
2021
ANALYSIS_CACHE_BYPASSES,
2122
ANALYSIS_CACHE_MISSES,
2223
BASE_GENERATOR_ENTRY,
@@ -166,7 +167,7 @@ def compare_builds(
166167
mode=mode,
167168
compile_args=compile_args,
168169
)
169-
check_cache_use(run=run, mode=mode)
170+
check_cache_use(run=run, mode=mode, models=models)
170171
results[label].append(run)
171172
if mode != COLD_MODE:
172173
_, head_python, head_dir = builds[1]
@@ -213,13 +214,21 @@ def _comparison(
213214
)
214215

215216

216-
def check_cache_use(*, run: CompileRun, mode: str) -> None:
217-
"""Fail a bypassing run, a warm run with misses, or an edit run that analysed nothing."""
217+
def check_cache_use(*, run: CompileRun, mode: str, models: int) -> None:
218+
"""Fail a bypassing full compile, a warm run with misses, or an edit that analysed nothing."""
218219

219220
misses: int | None = run.analysis_cache_misses
220221
if misses is None or mode == COLD_MODE:
221222
return
222223
bypasses: int = run.analysis_cache_bypasses or 0
224+
delta: bool = run.analysed_models is not None and run.analysed_models < models
225+
if mode == EDIT_MODE and delta:
226+
if misses + bypasses == 0:
227+
raise CompileComparisonError(
228+
f"{run.label} one-model edit delta compile analysed no model afresh, so the "
229+
"edit did not invalidate the edited model"
230+
)
231+
return
223232
if bypasses != 0:
224233
raise CompileComparisonError(
225234
f"{run.label} {mode} compile bypassed the analysis cache for {bypasses} models, so "
@@ -328,6 +337,11 @@ def _compile_once(
328337
timings_ms={name: value for name, value in numeric.items() if name in REPORTED_PHASES},
329338
analysis_cache_misses=numeric.get(ANALYSIS_CACHE_MISSES),
330339
analysis_cache_bypasses=numeric.get(ANALYSIS_CACHE_BYPASSES),
340+
analysed_models=(
341+
sum(numeric[name] for name in ANALYSED_MODEL_COUNTERS)
342+
if all(name in numeric for name in ANALYSED_MODEL_COUNTERS)
343+
else None
344+
),
331345
report=json.dumps(payload, sort_keys=True),
332346
)
333347

‎scripts/compile_performance_ratio/constants.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
}
2121
ANALYSIS_CACHE_MISSES: str = "analysis_cache_misses"
2222
ANALYSIS_CACHE_BYPASSES: str = "analysis_cache_bypasses"
23+
ANALYSED_MODEL_COUNTERS: tuple[str, ...] = (
24+
"analysis_batch_cache_hits",
25+
"analysis_entry_cache_hits",
26+
ANALYSIS_CACHE_MISSES,
27+
ANALYSIS_CACHE_BYPASSES,
28+
)
2329
MODELS_DIRECTORY: str = "models"
2430
MODEL_FILE_PATTERN: str = "*.sql"
2531
EDIT_COMMENT: str = "-- Benchmark edit {revision}.\n"

‎scripts/compile_performance_ratio/models.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class CompileRun:
1313
timings_ms: dict[str, int]
1414
analysis_cache_misses: int | None = None
1515
analysis_cache_bypasses: int | None = None
16+
analysed_models: int | None = None
17+
"""How many models the compile analysed; a delta compile analyses only the models it reran."""
1618
report: str = ""
1719
"""The JSON report without its timings, which an uncached compile must reproduce."""
1820

‎tests/unit/scripts/compile_performance_ratio/_helpers/_test_types.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class CacheUseTestCase:
5151
description: str
5252
run: CompileRun
5353
mode: str
54+
models: int = 3000
5455
expected_result: None = None
5556

5657

@@ -60,6 +61,7 @@ class CacheUseErrorTestCase:
6061
run: CompileRun
6162
mode: str
6263
expected_message: str
64+
models: int = 3000
6365

6466

6567
@dataclass(frozen=True)

‎tests/unit/scripts/compile_performance_ratio/_helpers/test_measure.py‎

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ def test_given_compile_runs_when_taking_phase_medians_then_reports_only_complete
7878
timings_ms={},
7979
analysis_cache_misses=1,
8080
analysis_cache_bypasses=0,
81+
analysed_models=3000,
82+
),
83+
mode=EDIT_MODE,
84+
),
85+
CacheUseTestCase(
86+
description="a delta edit analyses only the edited model, afresh",
87+
run=CompileRun(
88+
label="head",
89+
wall_seconds=1.0,
90+
cpu_seconds=1.0,
91+
timings_ms={},
92+
analysis_cache_misses=0,
93+
analysis_cache_bypasses=1,
94+
analysed_models=1,
8195
),
8296
mode=EDIT_MODE,
8397
),
@@ -110,7 +124,10 @@ def test_given_compile_runs_when_taking_phase_medians_then_reports_only_complete
110124
def test_given_observed_cache_use_when_checking_then_accepts_the_run(
111125
test_case: CacheUseTestCase,
112126
) -> None:
113-
assert check_cache_use(run=test_case.run, mode=test_case.mode) is test_case.expected_result
127+
assert (
128+
check_cache_use(run=test_case.run, mode=test_case.mode, models=test_case.models)
129+
is test_case.expected_result
130+
)
114131

115132

116133
@pytest.mark.parametrize(
@@ -138,10 +155,39 @@ def test_given_observed_cache_use_when_checking_then_accepts_the_run(
138155
timings_ms={},
139156
analysis_cache_misses=0,
140157
analysis_cache_bypasses=3000,
158+
analysed_models=3000,
141159
),
142160
mode=EDIT_MODE,
143161
expected_message="bypassed the analysis cache for 3000 models",
144162
),
163+
CacheUseErrorTestCase(
164+
description="a delta edit that analysed nothing afresh did not observe the edit",
165+
run=CompileRun(
166+
label="head",
167+
wall_seconds=1.0,
168+
cpu_seconds=1.0,
169+
timings_ms={},
170+
analysis_cache_misses=0,
171+
analysis_cache_bypasses=0,
172+
analysed_models=1,
173+
),
174+
mode=EDIT_MODE,
175+
expected_message="delta compile analysed no model afresh",
176+
),
177+
CacheUseErrorTestCase(
178+
description="a warm compile that bypassed the cache, even for few models, is rejected",
179+
run=CompileRun(
180+
label="head",
181+
wall_seconds=1.0,
182+
cpu_seconds=1.0,
183+
timings_ms={},
184+
analysis_cache_misses=0,
185+
analysis_cache_bypasses=1,
186+
analysed_models=1,
187+
),
188+
mode=WARM_MODE,
189+
expected_message="bypassed the analysis cache for 1 models",
190+
),
145191
CacheUseErrorTestCase(
146192
description="a warm compile that missed the cache is not an unchanged compile",
147193
run=CompileRun(
@@ -162,7 +208,7 @@ def test_given_unobserved_cache_use_when_checking_then_rejects_the_run(
162208
test_case: CacheUseErrorTestCase,
163209
) -> None:
164210
with pytest.raises(CompileComparisonError, match=test_case.expected_message):
165-
check_cache_use(run=test_case.run, mode=test_case.mode)
211+
check_cache_use(run=test_case.run, mode=test_case.mode, models=test_case.models)
166212

167213

168214
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)