Смена пространства выбрасывает слой, а не сверяет его поэлементно

#525 увёл оба списка сцены с `map()` на `repeat(items, (item) => item.id, …)`,
чтобы Lit не переиспользовал узлы по позиции и не проигрывал анимацию двери,
которой не было. Правка верная, но на плане с двумя сотнями маркеров она
оказалась дорогой ровно там, где пользы не приносит: при смене пространства
ключи не пересекаются вовсе, и `repeat` строит две карты ключей и обходит оба
списка, чтобы затем всё равно выбросить всё и создать заново.

Бисект по медиане `switchCycleMs` на `large-house`: 871,2 перед #525 → 953,5
после. На раннере эти 80 мс распадаются на шесть-девять дополнительных длинных
задач, и `longTask.countP95` вышел за порог стабильного гейта.

Теперь оба списка рендерятся как `keyed(space.id, repeat(…))`. Внешний ключ
делает смену пространства: поддерево выбрасывается целиком, дифа нет. Внутренний
остаётся, потому что состав списков едет и внутри пространства — у маркеров от
призраков редактора и живого синка, у проёмов от записи с нерешённым хостом,
которая живёт только в режиме plan, — а переходы на `.device-shell-frame`,
`.op-leaf` и `.op-arc` никуда не делись.

Замер после правки: `switchCycleMs` 889,1 против 936,0 на `main` и 871,2 до
#525. Потолок карточки поднят на одну строку — на `import { keyed }`;
переносить нечего, сам рендер не вырос ни на символ.

Issue: #534
User-Visible: yes
This commit is contained in:
Codex
2026-09-11 22:30:11 +03:00
parent a9a6d37bba
commit 5afdb644c7
55 changed files with 650 additions and 563 deletions
+7
View File
@@ -2,6 +2,13 @@
## Unreleased
- Switching between floors on a large plan is quick again. Every switch was
rebuilding the device markers the slow way — comparing two hundred old
markers against two hundred new ones only to throw all of them away — which
cost about a tenth of a second of a frozen card each time. Nothing looks
different, and the door that never moved still does not animate
([#534](https://github.com/Matysh/houseplan-card/issues/534)).
- The “Follows the sun” background no longer slows the plan down. The plan's
outer outline is a blur over the whole sheet, and it lived in the same layer
as the plan: any mouse movement made the engine re-run it. The outline now
+7
View File
@@ -8,6 +8,13 @@
## Не выпущено
- Переключение между этажами на большом плане снова быстрое. Каждое
переключение пересобирало маркеры устройств самым долгим способом — сверяло
двести старых маркеров с двумя сотнями новых, чтобы затем выбросить все, — и
это стоило около десятой доли секунды подвисшей карточки. Внешне не меняется
ничего, и дверь, которая никуда не двигалась, по-прежнему не анимируется
([#534](https://github.com/Matysh/houseplan-card/issues/534)).
- Фон «Следует за Солнцем» больше не замедляет план. Внешний контур плана —
это размытие по габариту всего листа, и оно жило в общем слое с планом: любое
движение мыши заставляло движок прогонять его заново. Теперь контур держится
+12 -12
View File
@@ -3,7 +3,7 @@
"fixture": "synthetic-only",
"chromium": "151.0.7922.34",
"oxipng": "oxipng 10.2.0",
"sourceFingerprint": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceFingerprint": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"captureScriptSha256": "9e4b0ae533407fe003a129078aec020f2c83d67cdb6fc6da696ce3d829beaeb5",
"command": "npm run build && node demo/docs/capture.mjs",
"scenarios": {
@@ -15,7 +15,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "76c35a87810e3dc6890bda7b43da133f57d8860031204a62cda7115c15950090"
},
"view-touch": {
@@ -26,7 +26,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "795585acb09488236ebb8028a7fcbd918404c5fe01560bb9b4559de13d441625"
},
"space-create": {
@@ -37,7 +37,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "9f0970de09772674c3156b9fc5b2d49de0ceb22be11ecf8b136047d37d100a84"
},
"room-contour-close": {
@@ -48,7 +48,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "0c354a79f9c3660788b6c5e889a27b6bd78b1f209dc0eef6bb43e2c1344028c4"
},
"plan-context-tray": {
@@ -59,7 +59,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "64169c543291bc4df806dcf8ff484b42c8ea55eb343323d945344e0e28f2ce97"
},
"device-editor": {
@@ -70,7 +70,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "3c8703175605fcf0387d654cd30783ecfd33e21743e70b45190a5ae1a8d355c2"
},
"device-display-preview": {
@@ -81,7 +81,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "5d6193202102f5e6d85567f1111fa105895b933979fbf369c6ba0b1029deb823"
},
"background-editor": {
@@ -92,7 +92,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "375900a29aa62632883ede6727b7dbb8b48cabe9d7d0e16425f9779c837f3dd9"
},
"room-card": {
@@ -103,7 +103,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "3d85424676c823ddca3fa7dab3cce089b6030e48c05d16d2d48d922c66c0cbd2"
},
"device-info": {
@@ -114,7 +114,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "ac962820f8e1c5cb5b042d39b18dc95905fa840cb2d4749060d991be4f6977c2"
},
"pdf-export": {
@@ -125,7 +125,7 @@
},
"theme": "light",
"language": "en",
"sourceSha256": "1a0b29e3e36eba71bc42630eceef108cf9a9bc82cc78aa7d1d047144086ae4f6",
"sourceSha256": "d11c6433c3b10ec39a97f45ea5a1ea80da8443b80f8ab34a6e7bd4bd70aee64a",
"imageSha256": "4537692fd57a3ed95528eddd748eee5cb6e456ffab7cc49169853d62459252cd"
}
},