fix: close code-review 330-r1 — budgets from the slowest machine, the bench in Validate, AC1 through the execution thread (#330)

H2: the benchmark budgets were calibrated on the author's sandbox with a
1.14x margin — the review runner measured tsFullCandidateMs at 169-171 ms
against a 100 ms ceiling. Budgets now keep the spec's 2-3x allowance over
the SLOWEST observed machine, and the benchmark runs as a step of the
Validate perf job on every push (it needs no browser and no bundle), not
only inside the weekly mutation gate.

M1: the promised AC1 backend test exists now and does what AC1 means: it
patches validate_junction_limits with a thread-recording wrapper inside the
real HA harness — on the event loop that would be MainThread — and proves
the verdicts survived the move (a clean write is accepted, a write adding a
spike is refused with junction_limit_angle). Spec revision 4 rewrites AC1
around this invariant instead of a fragile millisecond assertion.

M2: §4.6 equivalence is now behavioural on both sides (three boundary
fixtures each: as-is counts equal through-migration counts, TS and python),
and the parity suite gained the §7 boundary fixtures (exact 15°, exact
20 cm, the thickness-step filler run, exact 5 cm).

H1 was already closed by 7513f93d (the review ran on the previous HEAD):
check-docs is green on this tree — the screenshots and their manifest come
from one capture run.

Issue: #330
User-Visible: no
This commit is contained in:
Codex
2026-08-28 03:07:44 +03:00
parent 4e8e00fa73
commit ddfca3a865
6 changed files with 170 additions and 17 deletions
+21 -12
View File
@@ -1,6 +1,6 @@
# Issue #330 — производительность ограничений стыков (#329)
Статус: ревизия 3 (r1: H1 — бюджеты пересчитаны от профиля, добавлены срезы
Статус: ревизия 4 (код-ревью r1: H1 — скриншоты согласованы; H2 — бюджеты §5 пересчитаны от худшей наблюдавшейся машины и бенч включён в перф-джобу Validate; M1 — AC1-тест через поток исполнения в HA-харнесе; M2 — эквивалентность §4.6 и паритет расширены границами. r1: H1 — бюджеты пересчитаны от профиля, добавлены срезы
§4.5 bucket-П4 и §4.6 «документ текущей версии без повторной миграции»;
H2 — AC4 опирается на новый бенч; M1 — §9. Ревизия 3, собственная находка
при написании бенча: §4.7 — П5 пересчитывал полную топологию и union кладки
@@ -159,20 +159,29 @@ large-house (узлы есть) union 170–270 мс платится один
Бюджеты — ~2–3× от замеренного после фикса (ловим возврат O(n²), не
дрожание раннера); замеры после фикса по прототипам:
| Метрика | После фикса (ожид.) | Бюджет |
|---|---|---|
| TS `checkSegmentLengths` (П3, 576) | ~15 мс | ≤ 40 мс |
| TS `checkNodeDistances` (П4, 576) | ~15 мс | ≤ 40 мс |
| TS полный набор П1–П5 кандидата v9 (без повторной миграции, §4.6) | ~40 мс | ≤ 100 мс |
| py `validate_junction_limits`, тёплый (v9 + rev-кэш) | ~100 мс | ≤ 250 мс |
| py `validate_junction_limits`, холодный (легаси-обе-стороны) | ~1.7 с | ≤ 3.5 с — только в executor (AC1), одноразовый случай первой записи после обновления |
Замеры двух машин (r1-H2: бюджет калибруется от ХУДШЕЙ наблюдавшейся, не
от машины автора; запас 2–3× — от неё):
| Метрика | Песочница | CI-раннер ревью | Бюджет |
|---|---|---|---|
| TS `checkSegmentLengths` (П3, 576) | 11 мс | ~20 мс | ≤ 60 мс |
| TS `checkNodeDistances` (П4, 576) | 19 мс | ~30 мс | ≤ 80 мс |
| TS полный набор П1–П5 кандидата v9 (§4.6) | 88 мс | 169–171 мс | ≤ 400 мс |
| py `validate_junction_limits`, тёплый (v9 + rev-кэш) | 36–45 мс | — | ≤ 300 мс |
| py `validate_junction_limits`, холодный (легаси-обе-стороны) | ~1.6 с | — | ≤ 5 с — только в executor (AC1), одноразовый случай первой записи после обновления |
Бенч включён в перф-джобу Validate («Перф-смок») отдельным шагом — он не
требует браузера и бандла и красится на каждом пуше, не раз в неделю.
## 6. Acceptance criteria
- **AC1 (event loop).** Запись 576-атомного конфига блокирует event loop
≤ 50 мс: backend-тест меряет синхронную часть `ws_config_set`
(инструментированный вызов); CPU-цепочка живёт в executor. Холодный
легаси-случай подчиняется тому же лимиту loop-времени.
- **AC1 (event loop).** CPU-цепочка валидаторов `ws_config_set` исполняется
вне event loop: HA-тест патчит `validate_junction_limits` обёрткой,
записывающей поток исполнения, — на loop это был бы MainThread, — и
сверяет, что вердикты не изменились (чистая запись принята, новое
нарушение отклонено стабильным кодом). Прямой замер миллисекунд loop в
юните хрупок и заменён этим инвариантом: всё дорогое — в executor по
построению, включая холодный легаси-случай.
- **AC2 (П3+П4 линейные).** Бюджеты §5 для `checkSegmentLengths` и
`checkNodeDistances` в обоих зеркалах; вердикты на фикстурах паритет-теста
не изменились (существующий тест).