Профилирование фронта и бэка: стенд, замеры, отчёт (#202) #203

Open
aep wants to merge 28 commits from feat/202-perf-profiling into test
Owner

Refs #202

Профилирование фронта и бэка по жалобам заказчика: медленный скролл форм и медленное открытие модальных окон. Код приложения не менялся: git diff origin/test --stat -- api/src web/src api/alembic web/rsbuild.config.ts web/package.json api/requirements*.txt api/web пуст. Всё новое лежит в perf/, отчёт — perf/REPORT.md.

Что в PR

  • perf/ — воспроизводимый стенд: Postgres 16 в docker, API, prod- и profiling-сборки фронта через rsbuild preview с прокси. Генератор данных через HTTP API (масштаб 1 и удвоенный масштаб 2), сценарии Playwright + CDP (скролл, скролл при соавторе, модалки, память), замеры бэка (bench, pg_stat_statements, EXPLAIN), run-all.sh, скрипты разбора perf/analysis/.
  • perf/report-data/ — сводные данные прогонов 20261026-s1, 20261026-s2, 20261026-control-s1. Сырые трассы и heap snapshots (~4 ГБ) в git не попадают.
  • perf/REPORT.md — 13 проблемных мест с цифрами, file:line и приоритетом; статический разбор без замера; что не удалось проверить.
  • openspec/changes/perf-profiling/ — дизайн и решения, docs/superpowers/plans/2026-10-25-perf-profiling.md — план.

Топ-5 (CPU 1×, Apple M4; основная метрика — время главного потока на действие)

№ Что Насколько Приоритет
М1 Каждый шаг скролла таблицы перерисовывает все ~500 видимых ячеек 3–4 раза: стили emotion/sx на каждую ячейку, offsetHeight в measureElement, не задан memoMode (RealtimeTable.jsx:37-43, :344-441; tableConfig.js) 80–95 мс на шаг 200 px при бюджете кадра 16,7 мс; контрольный замер на CPU 4×: 350 мс P1
М2 Свод 2: нет колоночной виртуализации, ответ приходит целиком (Svod2Page.jsx:465-481; summary.py:93-121) 184–256 мс на шаг; ответ 31–53 МБ (s1) и 123–195 МБ (s2); API 1,1–7,3 с P1
М3 Правка ячейки дважды пересобирает весь лист; WebSocket обрабатывает сообщения соединения последовательно (0033_form2_old_sort.sql:1460-1466, :1527-1534; websocket.py:973-1130) 0,63 с на правку (1 154 строки), 1,46 с (2 092 строки); не больше ~1,6 правки/с на соединение P1
М4 Листы FORM_4 собираются рекурсивным агрегатом v3.jsonb_sum (0010_form4.sql:269-297; 0012_del_project.sql:1418-1481) GET 0,6 с на 110 строк, 1,55–1,7 с на 300 строк P1
М5 Открытие модалки перерисовывает всю таблицу; справочник ВСП не виртуализирован (RealtimeTable.jsx:106-108, :851-871; TableDictVsp.jsx:238-247) 75–93 мс на листах; справочник ВСП 150–195 мс (180 ВСП) → 500–610 мс (720 ВСП) P2

Память: число DOM-узлов, обработчиков и WebSocket за 20 циклов не меняется. JS-heap растёт на 24–44 КБ за цикл, на 20 циклах это неубедительно. Растут нативные объекты MediaQuery*, время цикла выросло на 12% (М13).

Решения человека (design.md, «Decisions made with the human»)

  • Замеры без троттлинга CPU, только 1×.
  • Основная метрика — суммарное время главного потока на действие.
  • Контрольный прогон CPU 4× только для топ-3–4 находок, 1 повтор, цифры помечены как «контрольные».
  • Отдельная строка о размерах ответов API с оговоркой «сеть не эмулировалась».

Rulings I made

  • R-1 (design #11): T3 заполняет svods/modal_pages манифеста по Routes.jsx. Цена ошибки: доработка T3 при T5/T7.
  • R-2: форм-модалки мерятся на малом и выращенном листе (@big) через perfkit/gen/grow.py, без пересоздания БД; grow запускается после скролл-сценариев. Фактически выращены FORM_2/AHR_UTILITY и AHR_SECURITY до 500 строк и FORM_4/CAP до 300; AHR_RENT и FORM_4/AHR остались малыми (отклонение исполнителя, одобрено ревью). Цена ошибки: БД после grow отличается от базовой, скролл по этим листам до и после grow несопоставим.
  • R-3: Task 10 разбит на T10a (run-all.sh) и T10b (анализ и отчёт), многочасовой прогон вёл контроллер. Цена ошибки: лишний диспатч.
  • R-4: на масштабе 2 — 1 повтор (PERF_S2_REPEATS=1) по правилу человека (3 повтора ≈ 13 ч), на масштабе 1 — 3 повтора. Цена ошибки: для масштаба 2 нет разброса и p95.
  • R-5: бота-соавтора на FORM_4/STRUCTURE не чиним, 6 замеров там переходят в «не проверено»: по коду на STRUCTURE нет правок через cell_updated. Цена ошибки: нет замера соавтора на FORM_4.
  • R-6: перед EXPLAIN вложенных запросов и контролем 4× данные масштаба 1 восстановлены (reset + gen s1 + grow s1). Цена ошибки: ~20 мин; профили и EXPLAIN сняты на FORM_2/AHR в 2 092 строки против 1 154 в основном прогоне, поэтому в отчёте сравнение идёт «на шаг».
  • R-7: отдельное sonnet-ревью T10b не проводилось (diff 4,7 МБ, в основном данные), T10b покрыт финальным opus-ревью. Цена ошибки: нет раундового ревью до финала.
  • Отклонения, принятые на ревью: у роли rf нет листов FORM_1 (они принадлежат ССП), поэтому соавтор и память гонялись на FORM_2/AHR, FORM_4/STRUCTURE и FORM_4/CAP.

Финальное ревью ветки (opus)

Critical — нет. Important I-1…I-4 и Minor M-1…M-12 исправлены (5f4afc0, bc52212), после scoped re-review — all findings addressed.

Deferred

Находки по приложению:

Маркер Суть
O-1 /api/v1/users/me отвечает 500 для email с доменом .local (EmailStr в response_model)
O-2 в api/requirements-dev.txt нет greenlet, без него падает alembic
O-4 FORM_4: add_line и правки O(n) (jsonb_sum), GET CAP на 300 строк — 1,7 с (REPORT М4)
O-5 свод 2: 31–47 МБ без пагинации; в «РФ» попадают строки ССП (REPORT М2)
O-6 POST /projects: гонка technical_number, 409 при параллельных запросах
O-7 POST /stages/form отвергает даты с часовым поясом; username ≥ 3 символов; STRUCTURE FORM_4 не меняется; WS program_added на STRUCTURE → 404
O-8 скролл тяжёлый уже на CPU 1×: 85–95 мс на шаг (REPORT М1/М2)
O-10 WS обрабатывает сообщения последовательно (≤ ~1,6 правки/с), 12–14% правок бота получают error-эхо (REPORT М3/М8)
O-12 открытие модалки перерисовывает всю таблицу (REPORT М5)
O-14 GET листа FORM_2/AHR — 876 мс, v_form_view (REPORT М3/М4)

Находки по инструментам perf/ (minor):

Маркер Суть
T1.1–T1.4 venv при падении pip; down оставляет внуков npx; all повторяет npm ci; нет пинов версий
T2.1–T2.5 округление _fmt; KeyError без сообщения; read_all; альтернатива медиане; Sheet.url и build_url
T3.2–T3.4 этапы DFIP в verify; захардкоженное 566; оценка времени
T4.1–T4.5 auth.ts перезаписывает токен; cleanup теста; путь к .venv; duration +100 мс; run_id undefined
T5.3–T5.8 wanted() для /filter; tabIndex; тест оси x; skipLog; сигнатура фильтра; строка в design
T6.2–T6.3 trailer; error-эхо бота не разобрано
T7.2, T7.5–T7.8 фиксированные ожидания 3000/1500 мс; grow-s1.json; манифест после листов; contract_number; широкие селекторы
T8.1–T8.6 edits_ok; влияние snapshot; эвристика ячейки; refresh токена; traceback memtrend; формулировка
T9.1–T9.4 allowlist BUILDERS; timeout setup; bench SKIP; done>=5
T10a.1, T10a.3–T10a.6 таймауты шагов; verify; оценка; trailer; старые network.jsonl с паролем стенда (gitignored)

Полная таблица находок со статусами — в ledger SDD (раздел ## Findings), при закрытии все deferred уйдут в follow-up issue.

Не проверено

  • Соавтор на FORM_4/STRUCTURE (R-5).
  • Refresh токена в длинной WS-сессии.
  • Свод 2 РФ на масштабе 2 упёрся в лимит 5 000 шагов.
  • py-spy (на macOS нужен root), заменён сравнением с X-DB-Time-Ms.
  • Сверхлинейный рост GET листа на масштабе 2.
  • Источник роста MediaQuery*.
  • Оверлеи в Calendar и tableHandlers.
  • Яндекс.Браузер, сеть и прод-ресурсы (1 vCPU / 4 ГБ).
  • Цена правки на FORM_4 в report-data (3,4 с — замер вне report-data).

🤖 Generated with Claude Code

Refs #202 Профилирование фронта и бэка по жалобам заказчика: медленный скролл форм и медленное открытие модальных окон. **Код приложения не менялся**: `git diff origin/test --stat -- api/src web/src api/alembic web/rsbuild.config.ts web/package.json api/requirements*.txt api/web` пуст. Всё новое лежит в `perf/`, отчёт — `perf/REPORT.md`. ## Что в PR - `perf/` — воспроизводимый стенд: Postgres 16 в docker, API, prod- и profiling-сборки фронта через `rsbuild preview` с прокси. Генератор данных через HTTP API (масштаб 1 и удвоенный масштаб 2), сценарии Playwright + CDP (скролл, скролл при соавторе, модалки, память), замеры бэка (bench, `pg_stat_statements`, EXPLAIN), `run-all.sh`, скрипты разбора `perf/analysis/`. - `perf/report-data/` — сводные данные прогонов `20261026-s1`, `20261026-s2`, `20261026-control-s1`. Сырые трассы и heap snapshots (~4 ГБ) в git не попадают. - `perf/REPORT.md` — 13 проблемных мест с цифрами, file:line и приоритетом; статический разбор без замера; что не удалось проверить. - `openspec/changes/perf-profiling/` — дизайн и решения, `docs/superpowers/plans/2026-10-25-perf-profiling.md` — план. ## Топ-5 (CPU 1×, Apple M4; основная метрика — время главного потока на действие) | № | Что | Насколько | Приоритет | |---|---|---|---| | М1 | Каждый шаг скролла таблицы перерисовывает все ~500 видимых ячеек 3–4 раза: стили emotion/`sx` на каждую ячейку, `offsetHeight` в `measureElement`, не задан `memoMode` (`RealtimeTable.jsx:37-43`, `:344-441`; `tableConfig.js`) | 80–95 мс на шаг 200 px при бюджете кадра 16,7 мс; контрольный замер на CPU 4×: 350 мс | P1 | | М2 | Свод 2: нет колоночной виртуализации, ответ приходит целиком (`Svod2Page.jsx:465-481`; `summary.py:93-121`) | 184–256 мс на шаг; ответ 31–53 МБ (s1) и 123–195 МБ (s2); API 1,1–7,3 с | P1 | | М3 | Правка ячейки дважды пересобирает весь лист; WebSocket обрабатывает сообщения соединения последовательно (`0033_form2_old_sort.sql:1460-1466`, `:1527-1534`; `websocket.py:973-1130`) | 0,63 с на правку (1 154 строки), 1,46 с (2 092 строки); не больше ~1,6 правки/с на соединение | P1 | | М4 | Листы FORM_4 собираются рекурсивным агрегатом `v3.jsonb_sum` (`0010_form4.sql:269-297`; `0012_del_project.sql:1418-1481`) | GET 0,6 с на 110 строк, 1,55–1,7 с на 300 строк | P1 | | М5 | Открытие модалки перерисовывает всю таблицу; справочник ВСП не виртуализирован (`RealtimeTable.jsx:106-108`, `:851-871`; `TableDictVsp.jsx:238-247`) | 75–93 мс на листах; справочник ВСП 150–195 мс (180 ВСП) → 500–610 мс (720 ВСП) | P2 | Память: число DOM-узлов, обработчиков и WebSocket за 20 циклов не меняется. JS-heap растёт на 24–44 КБ за цикл, на 20 циклах это неубедительно. Растут нативные объекты `MediaQuery*`, время цикла выросло на 12% (М13). ## Решения человека (design.md, «Decisions made with the human») - Замеры без троттлинга CPU, только 1×. - Основная метрика — суммарное время главного потока на действие. - Контрольный прогон CPU 4× только для топ-3–4 находок, 1 повтор, цифры помечены как «контрольные». - Отдельная строка о размерах ответов API с оговоркой «сеть не эмулировалась». ## Rulings I made - R-1 (design #11): T3 заполняет `svods`/`modal_pages` манифеста по `Routes.jsx`. Цена ошибки: доработка T3 при T5/T7. - R-2: форм-модалки мерятся на малом и выращенном листе (@big) через `perfkit/gen/grow.py`, без пересоздания БД; grow запускается после скролл-сценариев. Фактически выращены FORM_2/AHR_UTILITY и AHR_SECURITY до 500 строк и FORM_4/CAP до 300; AHR_RENT и FORM_4/AHR остались малыми (отклонение исполнителя, одобрено ревью). Цена ошибки: БД после grow отличается от базовой, скролл по этим листам до и после grow несопоставим. - R-3: Task 10 разбит на T10a (`run-all.sh`) и T10b (анализ и отчёт), многочасовой прогон вёл контроллер. Цена ошибки: лишний диспатч. - R-4: на масштабе 2 — 1 повтор (`PERF_S2_REPEATS=1`) по правилу человека (3 повтора ≈ 13 ч), на масштабе 1 — 3 повтора. Цена ошибки: для масштаба 2 нет разброса и p95. - R-5: бота-соавтора на FORM_4/STRUCTURE не чиним, 6 замеров там переходят в «не проверено»: по коду на STRUCTURE нет правок через `cell_updated`. Цена ошибки: нет замера соавтора на FORM_4. - R-6: перед EXPLAIN вложенных запросов и контролем 4× данные масштаба 1 восстановлены (reset + gen s1 + grow s1). Цена ошибки: ~20 мин; профили и EXPLAIN сняты на FORM_2/AHR в 2 092 строки против 1 154 в основном прогоне, поэтому в отчёте сравнение идёт «на шаг». - R-7: отдельное sonnet-ревью T10b не проводилось (diff 4,7 МБ, в основном данные), T10b покрыт финальным opus-ревью. Цена ошибки: нет раундового ревью до финала. - Отклонения, принятые на ревью: у роли rf нет листов FORM_1 (они принадлежат ССП), поэтому соавтор и память гонялись на FORM_2/AHR, FORM_4/STRUCTURE и FORM_4/CAP. ## Финальное ревью ветки (opus) Critical — нет. Important I-1…I-4 и Minor M-1…M-12 исправлены (5f4afc0, bc52212), после scoped re-review — all findings addressed. ## Deferred Находки по приложению: | Маркер | Суть | |---|---| | O-1 | `/api/v1/users/me` отвечает 500 для email с доменом `.local` (`EmailStr` в response_model) | | O-2 | в `api/requirements-dev.txt` нет `greenlet`, без него падает alembic | | O-4 | FORM_4: add_line и правки O(n) (`jsonb_sum`), GET CAP на 300 строк — 1,7 с (REPORT М4) | | O-5 | свод 2: 31–47 МБ без пагинации; в «РФ» попадают строки ССП (REPORT М2) | | O-6 | `POST /projects`: гонка `technical_number`, 409 при параллельных запросах | | O-7 | `POST /stages/form` отвергает даты с часовым поясом; username ≥ 3 символов; STRUCTURE FORM_4 не меняется; WS `program_added` на STRUCTURE → 404 | | O-8 | скролл тяжёлый уже на CPU 1×: 85–95 мс на шаг (REPORT М1/М2) | | O-10 | WS обрабатывает сообщения последовательно (≤ ~1,6 правки/с), 12–14% правок бота получают error-эхо (REPORT М3/М8) | | O-12 | открытие модалки перерисовывает всю таблицу (REPORT М5) | | O-14 | GET листа FORM_2/AHR — 876 мс, `v_form_view` (REPORT М3/М4) | Находки по инструментам `perf/` (minor): | Маркер | Суть | |---|---| | T1.1–T1.4 | venv при падении pip; `down` оставляет внуков npx; `all` повторяет `npm ci`; нет пинов версий | | T2.1–T2.5 | округление `_fmt`; KeyError без сообщения; `read_all`; альтернатива медиане; `Sheet.url` и `build_url` | | T3.2–T3.4 | этапы DFIP в verify; захардкоженное 566; оценка времени | | T4.1–T4.5 | `auth.ts` перезаписывает токен; cleanup теста; путь к `.venv`; duration +100 мс; `run_id` undefined | | T5.3–T5.8 | `wanted()` для `/filter`; tabIndex; тест оси x; skipLog; сигнатура фильтра; строка в design | | T6.2–T6.3 | trailer; error-эхо бота не разобрано | | T7.2, T7.5–T7.8 | фиксированные ожидания 3000/1500 мс; `grow-s1.json`; манифест после листов; `contract_number`; широкие селекторы | | T8.1–T8.6 | `edits_ok`; влияние snapshot; эвристика ячейки; refresh токена; traceback memtrend; формулировка | | T9.1–T9.4 | allowlist `BUILDERS`; timeout setup; bench SKIP; `done>=5` | | T10a.1, T10a.3–T10a.6 | таймауты шагов; verify; оценка; trailer; старые `network.jsonl` с паролем стенда (gitignored) | Полная таблица находок со статусами — в ledger SDD (раздел `## Findings`), при закрытии все deferred уйдут в follow-up issue. ## Не проверено - Соавтор на FORM_4/STRUCTURE (R-5). - Refresh токена в длинной WS-сессии. - Свод 2 РФ на масштабе 2 упёрся в лимит 5 000 шагов. - py-spy (на macOS нужен root), заменён сравнением с `X-DB-Time-Ms`. - Сверхлинейный рост GET листа на масштабе 2. - Источник роста `MediaQuery*`. - Оверлеи в Calendar и tableHandlers. - Яндекс.Браузер, сеть и прод-ресурсы (1 vCPU / 4 ГБ). - Цена правки на FORM_4 в report-data (3,4 с — замер вне report-data). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 28 commits 2026-10-26 12:40:23 +03:00
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Библиотека scroll.ts (scrollThrough) с тестами на фикстурах, сценарий
scroll.spec.ts: листы форм, отчёты проектов, своды 1/2, projects/summaries,
admin-контроль, смена фильтра свода. Параметры PERF_TARGETS/CPU_RATES/REPEATS/ROLES/AXES.

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
no_overflow вместо пустого complete, узкий catch по строкам, таймаут свода 2,
подписка на мутации до ввода фильтра и проверка эффекта фильтра, traced=1.

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Перечень модалок (modals.json), measureOpen с main_thread_ms, профиль
перерисовок React (reactProfile), сценарий modals.spec.ts, подкоманда
stand.sh web-profiling (:8081), генератор modals-inventory.md.

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
perfkit.gen.grow доращивает FORM_2 AHR_UTILITY/AHR_SECURITY до 500 и
FORM_4 CAP до 300 строк; у форм-модалок варианты @big.

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Сетевой лог сценариев, bench запросов, pg_stat_statements и EXPLAIN,
aggregate исключает трассировочные повторы (O-9).

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- perf/run-all.sh: масштабы 1 и 2, шаги reset -> gen -> verify -> stand ->
  preflight -> scroll -> coauthor -> grow -> modals -> modals_profiling ->
  memory -> memtrend -> [control4x] -> bench -> aggregate; лог и
  run-all.status.json, возобновление (PERF_STEPS, PERF_SKIP_RESET),
  сухой режим с оценкой длительности, PERF_S2_REPEATS/PERF_S2_TARGETS,
  контроль CPU 4x (PERF_CONTROL_TARGETS).
- Основная метрика: main_thread_ms и main_thread_ms_per_step в скролле
  (CDP TaskDuration), frame_excess_ms; в summary.md первыми строками.
- SQL-статистика по шагам: PERF_SQLSTATS_TAG -> sql/<шаг>/ (sqlstats --out).
- netlog: тела /auth/ не пишутся, поля password/token/secret вырезаются.
- scroll.spec: уникальные имена целей (лист ССП с суффиксом /ssp, год в
  отчёте проекта) - иначе Playwright не запускал файл из-за дублей.
- PERF_TRACE=0 для прогонов с одним повтором.
- README: scroll-coauthor, run-all, возобновление, без CPU 4/6 в матрицах.
- design.md: уточнена формулировка R-2, решения Task 10a.

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- C1: trace только на повторе 0 при числе повторов > 1 (lib/trace.ts
  shouldTrace) в scroll и scroll-coauthor: admin-контроль, control4x и
  PERF_S2_REPEATS=1 больше не теряют единственную запись (traced=1).
- I1: масштаб 2 - PERF_LOAD_TIMEOUT_MS=40 мин и PERF_TEST_TIMEOUT_MS=90 мин,
  если не заданы.
- I2: шаг aggregate падает при сбое perfkit.aggregate/копирования и если
  summary.json не создан; тесты run-all (perf/tests/test_run_all.py).
- M2: после modals_profiling останавливается preview :8081.
- README, design.md: решения раунда.

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- perf/analysis: разбор trace (timeline_breakdown), CPU-профилей с source maps
  (cpuprofile_top), heap snapshots (heapdiff), циклов памяти, сравнения масштабов,
  ручной EXPLAIN вложенных запросов (explain_manual), API против X-DB-Time-Ms
  (api_split), сводка горячих точек; тесты ядра в perf/tests/test_analysis.py
- perf/e2e/scenarios/hotspots.spec.ts: CPU-профиль, рендеры React, мутации DOM
  после фильтра, рост CSS-правил по циклам (вне run-all)
- prod-сборка с source maps: PERF_SOURCEMAP=1, perf/stand.sh web-sourcemap (:8082)
- perf/report-data/20261026-s1, 20261026-s2 (summary, sql, analysis, explain-manual),
  t5-types (иллюстрация CPU 6x)
- design.md: решения T10b без обсуждения

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- report-data/20261026-control-s1: CPU 4x, 1 повтор (FORM_2/AHR, свод 1 MAIN,
  свод 2 GO, модалка выбора ВСП на большом листе), отдельный run_id
- analysis/api-split: полное время API против заголовка X-DB-Time-Ms
  (вместо py-spy, которому на macOS нужен root)
- analysis/modal-renders, hotspots: рендеры модалок прогона s1, циклы CSS и
  matchMedia со вторым листом

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
perf/REPORT.md: резюме и ответы на жалобы заказчика, методика и окружение,
таблица 13 мест (file:line, доказательство, влияние, приоритет, подтверждено
замером), подробности, статический разбор без замера, что не проверено.

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- run-all.sh: копия run-all.status.json в report-data с относительными путями;
  пример control4x с отдельным тегом и предупреждением (I-3, M-8); очищены
  три закоммиченные копии статуса
- lib/modal.ts: long tasks по пересечению окна (tasksInWindow), тест (M-7)
- scale_compare.py: строки листов на момент скролла (до grow), пояснения (M-6)
- hotspots_summary.py: оговорка о разбавлении «на шаг» (M-5)
- netlog_sizes.py + report-data/20261026-s1/analysis/netlog-sizes.md (M-3)

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- REPORT: правки FORM_4 — вывод по коду, не замер (I-1); цена фильтра свода
  по записям основного прогона, hotspots — верхняя граница (I-2); М6 поднята
  до P1, пояснение состава топ-5 (I-4); формулировки кадров, малых листов,
  admin-контроля, М8, время прогона (M-1, M-2, M-9, M-11); раздел 6 дополнен,
  новый раздел 6а с находками при подготовке стенда (M-10, M-12, T7.3)
- README: контроль 4x с отдельным тегом и предупреждением (I-3), команды
  modal-renders и netlog-sizes (M-4), гипотезы в «Как читать» (T8.7)
- design.md: R-7, правило приоритетов и топ-5, решения волны исправлений
- план: заметка о замене CPU [1,4,6] решением человека (M-12)

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This pull request can be merged automatically.
You are not authorized to merge this pull request.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/202-perf-profiling:feat/202-perf-profiling
git checkout feat/202-perf-profiling
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/DFiP_Budget_planing#203
No description provided.