полнота точки — множество ключей, победитель — функция множества точек
- отношение победы было нетранзитивным: полнота (частичный порядок) плюс тай-брейк (тотальный) в попарной свёртке давали цикл, из-за которого одна и та же доставка меняла содержимое объекта при каждой пересборке - надмножество побеждает только при совпадении значений общих содержательных ключей: иначе точка без единого измерения вытесняла измерение - Less стал тотальным, isEmpty не материализует значение, имя метрики в координате столкновения обрезается, отпечаток витрины включает units и sealed - на живом архиве строгий no-op: 1737 объектов, содержимое совпало побайтово
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# Цена слияния на широкой доставке
|
||||
|
||||
**Приоритет:** средний
|
||||
|
||||
Вынуто ревью кода задачи `pravilo-sliyaniya-tochek` (профиль `deep`, враждебный
|
||||
проход и независимая реализация — независимо друг от друга).
|
||||
|
||||
## Оракул: измерено
|
||||
|
||||
Тело 63 МБ (в запросе ~200 КБ gzip — предел приёма 64 МиБ), 119 точек на ОДНОЙ
|
||||
координате:
|
||||
|
||||
```
|
||||
транзакция держалась 5.149 с, аллоцировано 6108 МБ, пик кучи 189 МБ
|
||||
```
|
||||
|
||||
При `busy_timeout` 5000 мс и `_txlock=immediate` параллельная доставка
|
||||
получает `SQLITE_BUSY`, `inTx` повторяет её до пяти раз (каждый повтор —
|
||||
полный пересчёт слияния), и на исчерпании попыток доставка уходит в
|
||||
`parse_status=failed`. Тело при этом в архиве остаётся, но пересборки, которая
|
||||
его подберёт, ещё нет.
|
||||
|
||||
Отдельный вклад, измеренный бенчмарком на часовом объекте нижнего слоя
|
||||
(3 600 точек):
|
||||
|
||||
```
|
||||
HashAll на объект 9.46 мс 6.7 МБ аллокаций
|
||||
Form одной точки 2.2 мкс
|
||||
```
|
||||
|
||||
`hashPoints` пересчитывает каноническую форму ВСЕХ точек часа на каждое
|
||||
слияние, включая неизменившиеся. Утверждение `docs/architecture.md` о
|
||||
дешевизне глубокого прохода («4400 сравнений хеша, почти все сойдутся»)
|
||||
стоимости самих сравнений не учитывает: чтобы сравнить хеш, его надо посчитать.
|
||||
|
||||
Часть цены задачей `pravilo-sliyaniya-tochek` уже снята: `isEmpty` больше не
|
||||
материализует значение (было 410 мс на точку 16.5 МБ), а разбор точки
|
||||
переиспользуется через `canon.Fields`. Осталось структурное.
|
||||
|
||||
## Что делать
|
||||
|
||||
1. Держать хеш каждой точки в `payload` рядом с координатами (`storedPoint`
|
||||
уже есть) и пересчитывать форму только для новых и выигравших столкновение
|
||||
— стоимость станет пропорциональна дельте, а не объёму часа.
|
||||
2. Считать `canon.Form` точки один раз на столкновение и переиспользовать в
|
||||
`Equal`, `Relate` и порядке вместо трёх независимых разборов.
|
||||
3. Проверять `ctx.Err()` в цикле по точкам: сейчас дедлайн свёртки неисполним,
|
||||
прервать слияние нечем.
|
||||
4. Оценить потолок числа кандидатов на одной координате: выбор победителя
|
||||
квадратичен по ним, и 119 точек на одну метку — вход, который приём
|
||||
принимает.
|
||||
|
||||
## Связано
|
||||
|
||||
- [otvet-i-svyortka](otvet-i-svyortka.md) — воркер убирает влияние на ответ
|
||||
приёму, но не на блокировку записи; задачи независимы.
|
||||
- [reindex-iz-arhiva](reindex-iz-arhiva.md) — подбирает доставки, ушедшие в
|
||||
`failed` по этой причине.
|
||||
Reference in New Issue
Block a user