Files
houseplan-card/docs/specs/451-render-performance.md
2026-09-04 22:03:23 +03:00

37 KiB
Raw Permalink Blame History

ТЗ #451 — фильтрация render и лёгкий live-слой взаимодействий

  • Issue: https://github.com/Matysh/houseplan-card/issues/451
  • Редакция: первая редакция для независимого ревью; статус определяется только метками issue
  • Тип / приоритет: bug / P1
  • Оценка: пользовательская ценность 10/10; ценность для разработки 10/10; сложность и риск 9/10
  • Область: общий lifecycle houseplan-card, HA render snapshot и registry, View, редакторы Плана/Устройств/Подложки, камера и continuous interactions, diagnostics, performance harness
  • Модель данных: без новых полей, миграции и backend-изменений
  • Связано: #34, #82, #137, #156, #380, #396, #449, demo/performance/README.md

1. Сценарий

Персона: администратор дома, который использует средний или большой план в Home Assistant на desktop, планшете или настенной панели.

Поверхности и момент: обычный View и все три редактора во время движения мыши, pan/pinch/zoom, рисования, размещения, перетаскивания, вращения или resize; также обычная работа карточки, когда HA присылает фоновые state ticks.

На измеренном плане с 5 пространствами, 139 маркерами и 144 устройствами один полный update занимает десятки миллисекунд. Hover запускает его почти на каждое движение указателя, pan дал 76 полных updates за четыре протяжки, а нерелевантные HA ticks продолжают делать ту же работу в покое. Пользователь видит рывки и замирания вплоть до 451 мс, хотя неподвижная уже нарисованная сцена сама по себе не требует постоянной работы.

2. Что человек увидит до и после

До: план отстаёт от указателя, hover и редакторские preview дёргаются, а фоновые изменения посторонних HA entities могут вызвать заметный фриз.

После: тот же план, те же эффекты и те же результаты действий двигаются плавно; HA-изменения, относящиеся к плану, остаются актуальными, а посторонние изменения не заставляют карточку заново строить всю сцену.

Преднамеренных визуальных изменений нет. После завершения любого жеста канонический итог и итоговый кадр совпадают с текущим поведением.

3. Проблема и установленные причины

3.1 Диагностика находится в горячем render-path

_renderBody() безусловно вызывает houseplanDiagnostics(). Метод снова обходит все сохранённые HA-привязки и вызывает _bindingStatus() для каждой, хотя render использует результат лишь в трёх диагностических data-* атрибутах корневого ha-card. На боевом плане это 99 resolutions и около 20–27 мс на каждый render во всех четырёх режимах.

Проверенный на живой странице cache одного результата уменьшил стоимость принудительного render примерно вдвое, а суммарные Long Tasks pan — на 70 %. Однако cache «навсегда» неверен: значения должны меняться при изменении registry, config или доступности привязки.

3.2 Continuous state реактивно перестраивает всю карточку

_view, _zoom, hover, draft и большая часть drag/preview state объявлены Lit state. Их изменение на каждом pointer/animation step планирует полный проход HouseplanCard.render(): комнаты, стены, проёмы, декор, Glow, солнце, устройства и подписи строятся заново, хотя между соседними шагами меняется только камера или небольшой интерактивный слой.

Уже существующий fast path initial Plan snap hover решает один частный случай, но не создаёт общего контракта для View и редакторов.

3.3 Любой новый объект hass считается причиной render

Карточка не отличает изменение используемой планом entity от изменения одной из сотен посторонних entities. Вместе с render сейчас выполняется и операционная обработка HA snapshot: registry authority, reconnect/load, activity и vacuum histories, device rebuild и visual-continuity snapshot. Просто вернуть false из shouldUpdate() недостаточно: это могло бы убрать видимый render вместе с обязательной обработкой входящего состояния.

3.4 Performance gate проверяет другие сценарии

Абсолютные hardMaxMs уже есть. Пробел состоит не в отсутствии абсолютного механизма, а в сценариях: panZoomMs измеряет один wheel transition, stateUpdateMs меняет участвующую entity, а настоящий drag, View hover, нерелевантный HA tick и количество тяжёлых render-проходов не проверяются. Постоянно дорогой путь поэтому может быть одинаковым в base и candidate и оставаться зелёным.

4. Scope

В issue входят:

  1. Разделение приёма каждого нового hass snapshot, операционной обработки и решения о визуальной инвалидизации.
  2. Явный dependency projection всех HA данных, которые использует план или открытая UI-поверхность, и пропуск полного render для нерелевантного tick.
  3. Cache статической части diagnostics с точной инвалидизацией; публичный support-report и три data-* атрибута остаются актуальными.
  4. Единый lightweight live-interaction путь для камеры, hover и непрерывных preview во View и трёх редакторах.
  5. Coalescing pointer/animation updates до не более одного лёгкого paint на animation frame без повторной шаблонизации тяжёлой сцены.
  6. Один полный reconciliation render после commit/cancel жеста; применение последнего отложенного релевантного HA snapshot в том же итоговом кадре.
  7. Сохранение desktop, touch/pen, flat/hidden-iso, kiosk, fixed-floor, visibility/reconnect и lazy-runtime контрактов.
  8. Новый performance-профиль или совместимое расширение harness с настоящими pointer series, абсолютными потолками, Long Task и структурными assertions.
  9. Unit, targeted smoke, canonical screenshots/golden и release artifacts.

5. Non-scope

Не входят:

  • изменение внешнего вида комнат, стен, проёмов, устройств, подсказок, Glow, солнечных лучей, пылесосов, декора или hidden iso;
  • изменение hit areas, snap tolerance, grid, gesture thresholds, animation duration/easing, click/double-click/long-press или commit/cancel semantics;
  • виртуализация SVG/DOM, spatial index, изменение числа отображаемых объектов;
  • оптимизация конкретных geometry algorithms, room labels или decor renderer, кроме прекращения их повторного вызова без причины;
  • изменение persisted config/layout, websocket/backend API, schema, import/export или миграция данных;
  • ослабление существующих relative/absolute performance budgets;
  • публичная настройка, feature flag или новое пользовательское сообщение.

6. Контракт входящих HA snapshots

6.1 Приём не равен render

Каждое присваивание card.hass = next обязано обновить актуальную ссылку на HA и пройти безопасный intake, даже если visual render не нужен. Intake продолжает:

  • отслеживать connection/reconnect и registry authority;
  • запускать начальную/повторную загрузку, когда она требуется;
  • поддерживать device roster, finite activity runtime и vacuum telemetry/trail;
  • обновлять данные, которыми воспользуются event handlers и HA service calls;
  • поддерживать visual-continuity lifecycle без публикации половины кадра.

Пропуск visual render не имеет права пропустить подписку, history point, terminal activity edge, vacuum sample, reconnect или capability change.

6.2 Dependency projection

Для решения о render существует один канонический набор зависимостей, а не отдельные списки в фильтре и в renderer. В него входят как минимум:

  • entity/device/area bindings всех сохранённых маркеров и их controls;
  • room temperature/humidity sources;
  • opening contact/lock references;
  • entities в live-text;
  • sun.sun, light/Glow sources, vacuum source/map/telemetry references;
  • entities и registry metadata, необходимые открытому dialog/picker/info card;
  • active/disabled/removed registry resolution для bindings;
  • top-level HA значения, влияющие на язык, локаль, units, theme, user/write permissions, capabilities, connection и frontend formatting.

Entity state считается изменившимся, если для dependency id изменилось наличие или identity соответствующего HA state object. Это включает изменение state, attributes, timestamps и unavailable/recovery без дорогого deep comparison. Изменение нерелевантной entity не инвалидирует visual frame.

Dependency set пересобирается после config/layout/marker/space/dialog/registry изменения до следующего решения о фильтрации. Если классификатор не может доказать нерелевантность snapshot, он fail-open: разрешает render.

6.3 Обычный режим и активный жест

  • Вне continuous interaction релевантный HA snapshot публикуется без новой намеренной задержки — в обычном ближайшем Lit update.
  • Нерелевантный HA snapshot не вызывает HouseplanCard.render() и не меняет тяжёлый DOM, но становится актуальным для последующих действий и intake.
  • Во время активного pan/pinch/resize/drag/draft релевантный HA snapshot не прерывает лёгкий live paint. Сохраняется только последний snapshot; сразу после pointerup или pointercancel он входит в единственный итоговый full render. Промежуточные snapshots не проигрываются кадр за кадром.
  • lostpointercapture, уход со страницы, смена mode/space и structural config change завершают либо отменяют interaction штатным общим terminal path и не оставляют pending snapshot навсегда. Структурное изменение не откладывается, если продолжение жеста с ним небезопасно.
  • HA actions и safety checks всегда читают последний принятый hass, а не отложенный visual snapshot.

7. Контракт diagnostics cache

  1. Полный обход marker bindings не выполняется из _renderBody() и не повторяется на camera/hover/editor pointer step.
  2. Cache хранит статический результат registry diagnostics и binding counts. Он инвалидируется при изменении marker/config binding lifecycle, registry revision/authority, active/disabled/removed metadata или наличия state, влияющего на binding status.
  3. Обычное изменение значения уже доступной entity не инвалидирует binding counts, если её классификация active/ha_disabled/orphaned/unverified не могла измениться.
  4. Три корневых атрибута сохраняют текущие имена и значения: data-ha-registry-access, data-ha-disabled-bindings, data-ha-unverified-bindings.
  5. Публичный houseplanDiagnostics() сохраняет форму и redaction. Динамический lastSuccessAgeMs вычисляется в момент вызова поверх cached core; для его роста не запускается timer и не инвалидируется plan render.
  6. После invalidation новый результат вычисляется не более одного раза до следующей смены dependency, независимо от количества render requests.

8. Контракт lightweight live-interaction слоя

8.1 Граница тяжёлой сцены

Тяжёлая сцена — room fills/outlines, physical walls, openings, saved decor, Glow/sun, device faces, room labels, vacuum trails и hidden-iso geometry — не перешаблонизируется из-за очередного pointermove или camera animation frame. Её DOM identity сохраняется в пределах interaction, если нет отдельной структурной причины для rebuild.

Вызов HouseplanCard.render() считается full render независимо от того, дал ли Lit затем минимальный DOM diff. Рендер отдельного lightweight child/layer full render карточки не считается.

8.2 Камера

Pan, pinch, wheel/camera transition, zoom buttons, room focus и double-fit обновляют все участвующие SVG viewBox, HTML overlay projection и зависящие от камеры размеры согласованно в одном RAF-coalesced live paint. Flat и hidden iso не расходятся; tooltip, device layer, room labels, locks, measure labels, vacuum puck и editor chrome остаются совмещены с планом.

Canonical _view/_zoom продолжают отражать реально показанный кадр, чтобы retarget/cancel/persistence контракты #82/#396/#449 не получили stale start. На terminal state выполняется один full reconciliation render и штатное сохранение viewport там, где оно происходило раньше.

8.3 Hover

Принятый владельцем Q2 включает обычный hover:

  • room fill/physical outline и room tooltip сохраняют нынешние content, visibility, pointer modality и настройку отключения tooltip;
  • device tooltip/LQI/temperature/humidity и текущие CSS hover states остаются;
  • координата tooltip может обновляться каждый RAF, не вызывая full render;
  • leave, touch suppression, mode/space switch, visibility change и removal очищают lightweight hover без ghost overlay;
  • hover никогда не меняет config/layout и не делает websocket writes.

8.4 Редакторские continuous interactions

Один и тот же принцип применяется ко всем состояниям, которые меняются на pointermove до commit:

Поверхность Live-содержимое
План wall chain/rubber-band, snap/conflict marker, column/opening preview и dimensions, wall/room resize preview и measurements, physical move/rotate
Устройства marker drag/position preview, align guides и связанный tooltip
Подложка line/shape draft, decor/furniture/image move/resize/rotate, placement preview, backdrop transform и measurements

Pointermove меняет только соответствующий lightweight layer или transform. Pointerup сохраняет тот же canonical результат, history entry и write, что до #451; cancel восстанавливает то же исходное состояние и не создаёт write. Pointerdown может выполнить отдельный full render, если действительно меняет selection/tool UI, но последующие move-события не повторяют его.

Все movement sources coalesce: между двумя animation frames применяется последняя позиция, но commit повторно использует последнюю canonical event coordinate/state, поэтому coalescing не теряет конечную точку.

9. UX, touch и accessibility

  • Внешний вид до/после settled state должен быть pixel-equivalent с текущим dev; намеренных golden diffs нет.
  • Mouse, touch и pen сохраняют pointer capture, pan threshold, pinch ownership, click suppression и pointercancel поведение.
  • Hover остаётся только на устройствах с fine hover capability; touch не получает синтетический ghost hover.
  • Keyboard/Escape/Ctrl+Z и focus order не меняются.
  • Reduced motion сохраняет atomic camera result; forced colours, dark/light, kiosk, fixed-floor и read-only не получают отдельной ветки поведения.
  • Новых текстов, контролов, ARIA-элементов и i18n keys нет.

10. Модель данных, совместимость и безопасность

  • Persisted config/layout и backend payload не меняются; migration/write-back отсутствуют.
  • Старые планы автоматически получают ускорение после обновления frontend.
  • Оптимизация не изменяет HA service calls, permission checks, destructive confirmations, registry redaction или support-report contents.
  • Не вводятся worker, network request, dependency или глобальный shared cache между экземплярами карточки.
  • Несколько карточек на dashboard имеют независимые interaction queues, dependency sets и diagnostics cache.
  • Disconnect удаляет RAF/listener/observer и pending interaction state; warm remount не переносит незавершённый gesture в новый экземпляр.

11. Performance и наблюдаемость

11.1 Новый профиль

Добавляется отдельный large-house-interaction-v1 на существующем детерминированном large-house fixture, чтобы не менять смысл large-house-v1. Один runner/harness обязан оставаться способен измерить base до #451 и candidate; новые private поля сначала объявляются optional с честным fallback либо счётчики собираются внешним instrumentation.

После warm-up профиль выполняет:

  1. 120 View hover moves по room/device/miss;
  2. четыре pan drag по 20 moves и terminal pointerup;
  3. camera wheel/transition и pinch series;
  4. не менее трёх representative editor series: Plan draw/snap, room resize и Decor furniture/shape transform; targeted smoke покрывает остальную матрицу;
  5. 30 нерелевантных HA ticks и один релевантный tick;
  6. релевантный HA tick в середине drag с проверкой deferred-last-wins frame.

11.2 Структурные assertions

Для измерительного окна после начального settled frame:

  • 120 hover moves: 0 full renders;
  • каждое pan/pinch/editor move-series: 0 full renders между start и terminal event и не более 1 terminal full render;
  • 30 нерелевантных HA ticks: 0 full renders;
  • один релевантный HA tick вне gesture: ровно 1 full render;
  • несколько релевантных ticks внутри gesture: 0 промежуточных и ровно 1 terminal full render с последним состоянием;
  • camera/hover/editor windows: 0 полных marker-binding diagnostic scans;
  • static heavy-scene node identity/count, config, layout и websocket writes остаются стабильны; preview commit/cancel checks выполняются отдельно.

Assertions fail the runner независимо от timing result. RAF paints и renders выделенного lightweight child считаются отдельными метриками и не маскируются.

11.3 Абсолютные цели

Для профиля при тех же CI browser/runtime условиях задаются base-relative пределы и следующие bootstrap hardMaxMs. Они намеренно существенно ниже опубликованного в issue времени полных updates одного pan-сценария — 3 432 мс — и согласованы с существующим panZoomMs: 500 ms. Для hover потолок 500 мс на 120 moves означает в среднем не более 4,2 мс на событие против замеренных в issue 98,9 мс на полный update:

Метрика Абсолютный потолок
120 View hover moves 500 мс
4 × 20 pan moves + terminal 500 мс
wheel/pinch camera series 500 мс
120 representative editor moves + terminal 750 мс
30 нерелевантных HA ticks 250 мс

Для каждого pointer-series дополнительно: maxSingleLongTaskMs <= 150, longTaskTotalMs <= 300, longTaskCount <= 3. Эти потолки — bootstrap safety limits, а не разрешение расходовать весь budget; relative comparison остаётся. Ослабление существующих budgets запрещено. Первый paired Linux artifact должен быть описан в review/release evidence; ужесточение после него допустимо отдельной обоснованной правкой, ослабление — только через новый review.

12. Acceptance criteria

  • AC1 (unit + code review; разработчик/ревьюер): HA intake отделён от visual invalidation; нерелевантный snapshot обновляет актуальный hass и lifecycle/history, но не вызывает HouseplanCard.render().
  • AC2 (unit + targeted smoke; разработчик): изменение каждой категории dependency из §6.2 вызывает актуальный render, а изменение посторонней entity — нет; unknown classifier path fail-open и не оставляет stale UI.
  • AC3 (unit + targeted smoke; разработчик): activity/vacuum samples, reconnect/load, registry subscription, permissions и action safety работают при серии skipped visual ticks; action использует последний hass.
  • AC4 (unit + smoke; разработчик): diagnostics binding scan отсутствует в render/pointer path, cache инвалидируется по §7, три data-* атрибута и redacted public report актуальны, lastSuccessAgeMs растёт без repaint timer.
  • AC5 (smoke + performance; разработчик): View hover, pan, pinch, wheel/camera animation и double-fit соблюдают render-count assertions §11.2; все SVG/HTML/iso layers остаются совмещены на каждом captured frame.
  • AC6 (smoke + performance; разработчик): Plan draw/snap/opening/column, physical move/rotate, room resize, device drag, decor draft/move/resize/rotate, furniture/image placement и backdrop transform не вызывают full render на каждый move; terminal commit/cancel даёт один согласованный full frame.
  • AC7 (unit + smoke; разработчик): серия relevant HA updates во время gesture применяет только последний snapshot сразу после всех terminal paths; irrelevant updates не создают pending render.
  • AC8 (unit + smoke; разработчик): coalescing сохраняет конечную pointer coordinate, snap/geometry result, history, save count, pointer capture, cancel/undo и no-extra-write контракты для mouse/touch/pen.
  • AC9 (golden + canonical screenshots; разработчик/владелец): settled View, hover/tooltip, все три редактора, dark/light, forced colours, kiosk, fixed-floor и hidden iso не имеют непредусмотренных pixel diffs; screenshots приложены к handoff/review.
  • AC10 (performance; разработчик): новый interaction profile проходит все structural, absolute и base-relative checks §11; прежние ordinary, isometric, plan-snap и Glow profiles проходят без ослабления budgets.
  • AC11 (typecheck + unit + build; разработчик): implementation-loop gates зелёные; перед beta зелёные golden, smoke и performance по runbook; Linux CI остаётся каноном полного HA harness.
  • AC12 (schema/backend/i18n review; ревьюер): persisted model, backend, import/export, HA API, i18n strings и dependencies не изменены; новые caches bounded per card и очищаются при disconnect.
  • AC13 (documentation review; разработчик/ревьюер): demo/performance/README.md описывает новый профиль, counters, budgets и локальный запуск; оба changelog содержат пользовательский эффект со ссылкой на #451.

13. План автотестов

13.1 Unit

  • pure dependency classifier: relevant/irrelevant/missing state, attributes, all source kinds, top-level locale/theme/units/user/connection and fail-open;
  • dependency-set rebuild после marker/config/dialog/registry changes;
  • HA intake с skipped render: activity terminal edge, vacuum sample, reconnect, latest action snapshot и no duplicate processing;
  • gesture gate state machine: begin/update coalescing/end/cancel/forced cancel, latest-relevant-wins и irrelevant-no-pending;
  • diagnostics cache keys, one scan per invalidation, state-presence transition, dynamic age и redaction;
  • camera live projection: clamp, anchor, retarget, persistence and cleanup.

13.2 Targeted production-bundle smoke

Инструментировать full render count, lightweight paints, diagnostics scans, heavy node identity, writes и visible state. На production bundle пройти:

  • room/device/miss hover and leave;
  • mouse pan, wheel, pointercancel; touch pan/pinch and lost capture;
  • #449 double-fit и interrupted/retargeted camera transition;
  • матрицу interactions из AC6 с несколькими move events, commit и cancel;
  • relevant/irrelevant HA ticks вне и внутри gesture;
  • space/mode switch, visibility hide/show, disconnect/reconnect и warm remount;
  • flat/iso, normal/fixed-floor/kiosk/read-only.

Synthetic events обязаны доходить до production handlers; 0 событий у handler не принимается как доказательство 0 renders.

13.3 Golden, performance и release

  • implementation loop: npm run typecheck, npm test, npm run build;
  • после изменения src/** — canonical screenshots по workflow из PROCESS.md §8 (demo/docs/capture.mjs, затем только после проверки npm run docs:accept), inspection и существующие golden; любой diff исследуется;
  • перед beta — полный smoke/golden/performance gate по runbook;
  • full performance сравнивает candidate/base на одном Linux runner и публикует отдельный interaction artifact со structural diagnostics;
  • три bundle snapshots после release build должны совпадать.

14. План реализации и затрагиваемые файлы

Ожидаемые точки изменения:

  1. src/houseplan-card.ts — HA intake/visual invalidation, diagnostics cache, gesture terminal reconciliation и подключение live layers.
  2. Новый либо существующий узкий src/*render*/src/*interaction* module — pure dependency classifier, bounded state machine и RAF scheduler; точные имена не являются контрактом.
  3. src/houseplan-editor-runtime.ts — маршрутизация continuous editor previews в lightweight invalidation без изменения canonical commit logic.
  4. Unit tests для classifier/cache/controller и regression tests существующих camera/editor controllers.
  5. Targeted demo/smoke_*.mjs — production-bundle render-count и interaction matrix; обновление smoke runner/package scripts при необходимости.
  6. demo/benchmark_large_house.mjs, demo/performance/card-contract.mjs, новый budget/profile и evaluator/report plumbing — large-house-interaction-v1.
  7. demo/performance/README.md и оба changelog.

Реализация сначала выделяет pure contracts и diagnostics cache, затем HA filter, затем camera/hover live path, затем редакторские consumers. Нельзя массово снять state: true, пока у каждого изменяемого состояния нет проверенного live paint и terminal reconciliation path.

15. Release-артефакты

Изменение пользовательски заметно как исправление зависаний, поэтому основной implementation commit имеет User-Visible: yes и в том же коммите обновляет:

  • docs/CHANGELOG.md;
  • docs/CHANGELOG.ru.md.

Также обновляются:

  • demo/performance/README.md;
  • budget/profile и machine-readable performance report;
  • canonical screenshots/golden evidence без ожидаемого визуального изменения;
  • targeted smoke artifacts и full performance comparison.

Новые user-guide/i18n/security artifacts не требуются. Выпуск — обычной beta по разделу 8 release runbook; issue не закрывается автором реализации.

16. Риски и снижение

Риск Вероятность / ущерб Снижение
Фильтр ошибочно считает relevant HA tick посторонним средняя / высокий единый dependency authority, fail-open, матрица всех consumers и dialog states
Пропуск render одновременно пропускает activity/vacuum/reconnect intake высокая / высокий отдельный intake contract и тесты серий skipped ticks
Lightweight DOM расходится с canonical state средняя / высокий один state machine, last-event commit и обязательный terminal reconciliation
Несколько SVG/HTML/iso слоёв получают разные camera frames средняя / высокий один atomic projection writer и frame screenshots
Gesture оставляет pending HA/RAF после cancel/disconnect средняя / высокий единый terminal cleanup и lifecycle matrix
Child render формально скрывает прежнюю тяжёлую работу средняя / средний отдельные full/light counters, heavy-node identity и timing gate
Новый harness ломает сравнение со старым base средняя / высокий новый profile id, optional contract/fallback и тест candidate/base
Слишком мягкий timing budget снова пропускает проблему средняя / высокий structural assertions обязательны; absolute + relative gates, paired artifact review

17. Откат

Откат — revert implementation commit(ов) #451 и нового interaction profile. Данные и backend не требуют rollback/migration. Если дефект найден только в одном live interaction, допускается временно вернуть этому interaction прежний reactive path отдельным аварийным commit, не отключая безопасный diagnostics cache и HA filter, но такой fallback обязан иметь issue и regression proof.

18. Принято предположительно, поменять свободно

Ниже технические решения, не являющиеся продуктовым выбором владельца:

  • dependency projection может переиспользовать RenderDeviceSnapshot, но имеет один источник истины и включает зависимости всего сохранённого плана;
  • lightweight слой может быть Lit child component, imperative DOM projection или их комбинацией, если full/light counters и cleanup contracts соблюдены;
  • public diagnostics складывается из cached static core и динамического age;
  • точные private field/helper names и разбиение unit/smoke файлов свободны;
  • representative editor cases живут в performance profile, полная матрица — в deterministic smoke, чтобы timing fixture не превращался в функциональный e2e-комбайн.

Продуктовые решения владельца не предположительны: Q1 — relevant HA updates во время жеста применяются последним итоговым кадром; Q2 — обычный hover входит в #451 и сохраняет текущие эффекты через lightweight слой.