diff --git a/applications/PoP/docs/perf_l11_room15.md b/applications/PoP/docs/perf_l11_room15.md index 52d25fc..d6c12ee 100644 --- a/applications/PoP/docs/perf_l11_room15.md +++ b/applications/PoP/docs/perf_l11_room15.md @@ -179,6 +179,44 @@ if ((curr_modifier & 0x7F) < 6) { скорее всего перераскладка кода банка 3 компилятором; проверять отдельно не стали, знак верный. +## 7. ТЯЖЁЛАЯ позиция: Кид на шаг правее [замер 2026-08-19] + +Поставлена пользователем: один осторожный шаг вправо (x = 106 вместо 99, +колонка та же). Спрайт Кида начинает пересекаться с тайлом (0,3), где +одновременно чомпер и пламя факела — и `skip_mask` перестаёт его +пропускать. + +| фаза | лёгкая | **тяжёлая** | разница | +|---|---:|---:|---:| +| синяя | 259 500 | 257 520 | −1 980 | +| зелёная (медиана) | 181 068 | 180 870 | −198 | +| **циан** | 187 761 | **319 842** | **+132 081** | +| **работа (медиана)** | 628 542 | **758 358** | **+129 816** | +| работа (максимум) | 744 384 | **876 612** | | + +**Период кадра: 4 растра в 335 кадрах, 5 растров в 123 (27 %).** Это уже +не «стабильно медленно», а рывки: каждый четвёртый кадр длиннее соседних. + +Разбор циана показывает, куда ушли 132 тысячи: + +| участок | лёгкая | тяжёлая | +|---|---:|---:| +| `check_mirror` | 3 198 | 3 198 | +| `mob_draw` + `guard_over_kid` + `skip_mask` | 34 374 | 18 672 | +| **`pop_char_draw(KID)`** | **204** | **54 738** | +| соперник: `char_draw` + `char_fore` | 145 896 | 149 748 | +| **`fore_needed` + `char_fore(KID)` + борта** | **4 356** | **93 486** | + +То есть Кид из «пропущен за 204 такта» превращается в полноценного +персонажа за ~144 000 — ровно столько же, сколько стоит страж. + +**Главный вывод замера: самая дорогая единичная статья кадра — это +fore-проход персонажа.** 62 778 у стража и ~89 000 у Кида, вместе около +**152 000, то есть 20 % работы кадра**. У Кида он дороже потому, что в его +футпринте лежит чомпер, а у чомпера есть собственный передний слой +(`POP_CHOMP_FRAM_FOR`), который перерисовывается поверх персонажа каждый +кадр. + **Полная очередь оптимизаций с оценками — [`perf_registry.md`](perf_registry.md).** Там же разложена цена одного блита фона по этапам (замер 2026-08-19, 1603 блита) и модель зелёной фазы этой сцены. diff --git a/applications/PoP/docs/perf_registry.md b/applications/PoP/docs/perf_registry.md index 300a9a6..0358c3d 100644 --- a/applications/PoP/docs/perf_registry.md +++ b/applications/PoP/docs/perf_registry.md @@ -150,7 +150,39 @@ Новое, найдено 2026-08-19. -### P3. Персонажи будятся каждый кадр [модель: −70 000, следствие P1] +### P14. Fore-проход персонажа — 62 778…89 000 НА ПЕРСОНАЖА [замер 2026-08-19] + +**Самая дорогая единичная статья кадра: около 152 000 на двоих, 20 % работы.** + +`pop_char_fore` = два трамплина в банк 2 (`pop_fore_set_clip` + +`pop_fore_over_char`) плюс обход тайлов футпринта, в каждом `fore_tile`. +У Кида дороже, чем у стража, потому что в его футпринте лежит чомпер, а у +чомпера есть собственный передний слой (`POP_CHOMP_FRAM_FOR`), который +перерисовывается поверх персонажа каждый кадр. + +Что можно пробовать, по возрастанию радикальности: + +1. слить два трамплина в один вызов (мелочь, ~4 000); +2. **P10** — брать футпринт из физики, а не считать заново (−11 574 на + проход, то есть до −23 000 на двоих); +3. гейт по сигнатуре: пропускать проход, если не изменились ни кадр + персонажа, ни тайлы его футпринта. **Это расхождение с оригиналом** — + он рисует foretable безусловно; +4. **P13** — objtable и отложенные таблицы: у оригинала «посетить тайл» + стоит копейки именно потому, что таблицы только копят записи. + +### P3. Персонажи будятся каждый кадр ✅ ЧАСТИЧНО СБЫЛОСЬ + +**В лёгкой позиции — да:** после P1 `pop_char_draw(KID)` стоит 204 такта, +метка от чомпера до Кида больше не дотягивается. + +**В тяжёлой позиции — нет:** стоит Киду шагнуть на 7 пикселей вправо, и его +спрайт пересекается с тайлом чомпера и пламени, `skip_mask` перестаёт +пропускать, и он снова стоит ~144 000 (54 738 draw + ~89 000 fore). То +есть выигрыш P3 держится только пока персонаж не подошёл к анимированному +тайлу — а в игре он к нему подходит постоянно. + +Исходная оценка (−70 000) была: heal 141 048 + отрисовка 148 566 = 290 000 тактов (36 % работы) уходят на то, что `pop_char_skip_mask` не может пропустить ни Кида, ни стража: фон трогают @@ -294,67 +326,71 @@ BUG-LATTICE-DOORTOP, BUG-SEAM-WEDGE-1) — только отдельным за ## 4. ПЛАН РАБОТ — состояние между сессиями Рабочий чеклист. Правило: одна позиция = один заход = один коммит с замером -до/после на сцене 11/15. Замер обязателен даже когда «очевидно» — из шести -сделанных позиций две дали не то, что ожидалось. +до/после на сцене 11/15. Замер обязателен даже когда «очевидно» — из семи +закрытых позиций ТРИ дали не то, что ожидалось (P1 — вдвое меньше, P2a — +почти ничего, таблицы порогов — регресс). -| # | что | статус | факт | -|---|---|---|---| -| P5 | `loose_tick`: гейты холостого хода | ✅ **сделано** 2026-08-19 | −33 840 на кадре (ждали −28 000) | -| P2 | замер синей фазы | ✅ замерено 2026-08-19 | гипотеза «трамплины» отвергнута | -| P6 | замер `process_trobs` | ✅ замерено 2026-08-19 | 11 058 префетч + ~43 000 цикл | -| P1 | чомпер: перерисовка только при фазе < 6 | ✅ **сделано** 2026-08-19 | −110 802 (ждали −160 000) | -| P2a | `coll_scan` в 8 бит + снят с IX | ✅ **сделано** 2026-08-19 | −3 486 в коллизиях, −2 892 на кадре | -| P2b | луч видимости: колонки + один банковый вызов | ✅ **сделано** 2026-08-19 | −26 448 (ждали −30 000) | -| P4 | накладные блита (4 правки) | ⬜ **следующее** | ждём −28 000 | -| P11 | мелочи с известной ценой | ⬜ | ждём −26 000 | -| P10 | футпринт персонажа из физики | ⬜ | ждём −23 000 | -| P6a/P6b | `trob_modif` из цикла, кэш префетча | ⬜ | ждём −20 000 | -| P7 | раскол `draw_tile` (G5) | ⬜ | для 13/23, не для 11/15 | -| P8/P9 | HEAL-WIDTH + G8 | ⬜ обязательная | для сцен с плитами | -| P12 | снять оснастку | ⬜ ПОСЛЕДНЕЙ | без неё не мерить | +### Закрыто -### Достижим ли период 3 растра — арифметика после замеров +| # | что | факт | +|---|---|---| +| P5 | `loose_tick`: гейты холостого хода | **−33 840** (ждали −28 000) | +| P1 | чомпер: перерисовка только при фазе < 6 | **−110 802** (ждали −160 000) | +| P2b | луч видимости: колонки + один банковый вызов | **−26 448** (ждали −30 000) | +| P2a | `coll_scan` в 8 бит + снят с IX | **−2 892** (крупной статьи в физике нет) | +| P3 | Кид перестал будиться каждый кадр | сбылось само после P1 — но только в ЛЁГКОЙ позиции | +| P2/P6 | замеры синей фазы и `process_trobs` | гипотеза «трамплины на спецсобытиях» отвергнута | +| — | замер цианной фазы | крупного лишнего в отрисовке персонажа нет | -Работа сейчас **767 928**, цель **430 000**, снять надо **338 000**. Что -известно и посчитано: +### Осталось, по убыванию ожидаемого эффекта -| источник | ожидание | -|---|---:| -| ~~P1 (чомпер)~~ | ~~−160 000~~ → **сделано, −110 802** | -| P3 (Кид перестанет будиться) | −70 000 — **под вопросом**, см. ниже | -| P2b (гейт луча видимости) | −30 000 | -| P4 (накладные блита) | −28 000 | -| P11 (мелочи) | −26 000 | -| P10 (футпринт из физики) | −23 000 | -| P6a+P6b | −20 000 | -| **сумма оставшегося** | **−197 000** | +| # | что | ожидание | риск | комментарий | +|---|---|---:|---|---| +| **P14** | **fore-проход персонажа** — 62 778 у стража, ~89 000 у Кида | **до −80 000** | высокий | НОВОЕ, самая дорогая статья кадра (20 %). Включает P10 как первый шаг | +| P4 | накладные блита (4 правки) | −28 000 | низкий | 6 126 фиксированных на любой блит | +| P11 | мелочи с известной ценой | −26 000 | низкий | `clip_char_top` 8 658 подтверждён замером | +| P10 | футпринт персонажа из физики | −23 000 | средний | часть P14 | +| P6a/P6b | `trob_modif` из цикла, кэш префетча | −20 000 | низкий | тот же паттерн трамплина в цикле | +| P7 | раскол `draw_tile` (G5) | −50 000 в 13/23 | средний | в 11/15 не играет | +| P8/P9 | HEAL-WIDTH + G8 | 5-6 % цены heal'ов | низкий/средний | **обязательная** по решению пользователя; для сцен с плитами | +| P13 | objtable + отложенные таблицы, единый проход по тайлам | не оценено | очень высокий | большой рефакторинг слоя фона | +| P12 | снять оснастку | −6 000 | нулевой | **последней**: без неё не мерить | -**После P1 картина изменилась к худшему.** Снять с дорогого кадра надо -336 000, а всё оставшееся в списке даёт 197 000 — и это при оптимистичных -оценках. Вдобавок P3 (Кид перестанет будиться) теперь под вопросом: циан -после P1 не сдвинулся ни на такт (187 761), то есть метки от чомпера и -факелов продолжают будить обоих персонажей в каждом кадре. - -Значит без **P2a — разбора `pop_phys_tick`** (105 246 тактов на физику двух -НЕПОДВИЖНЫХ персонажей, цена измерена, причина не найдена) период 3 растра -не берётся. Это и есть следующая крупная позиция. - -**Текущее состояние бюджета 11/15:** +### Текущее состояние бюджета | | работа | синяя | зелёная | циан | период | |---|---:|---:|---:|---:|---:| | до оптимизации | 801 768 | 293 238 | 320 916 | 187 758 | 4 растра | -| после P5 | 767 928 | 285 864 | 294 384 | 187 764 | 4 растра | -| после P1 (медиана) | **657 882** | 286 503 | 183 420 | 187 761 | 4 растра | -| после P1 (дорогой кадр, 40 %) | 765 936 | 286 503 | 291 888 | 187 761 | 4 растра | -| после P2a (медиана) | 654 990 | 283 215 | 183 798 | 187 812 | 4 растра | -| после P2b (медиана) | **628 542** | 259 500 | 181 068 | 187 761 | 4 растра | +| после P5 | 767 928 | 285 864 | 294 384 | 187 764 | 4 | +| после P1 (медиана) | 657 882 | 286 503 | 183 420 | 187 761 | 4 | +| после P2a | 654 990 | 283 215 | 183 798 | 187 812 | 4 | +| **после P2b (лёгкая позиция)** | **628 542** | 259 500 | 181 068 | 187 761 | 4 | +| **ТЯЖЁЛАЯ позиция (Кид на шаг правее)** | **758 358** | 257 520 | 180 870 | **319 842** | **4 и 5** | -Цель — уложить РАБОТУ в 430 000 (тогда период станет 3 растра вместо 4; -хвост кадра — три `gfx_wait_vsync`). Осталось снять **228 000** с медианы -и **336 000** с дорогого кадра. Считать надо по ДОРОГОМУ: период задаётся -каждым кадром отдельно, и пока дорогие кадры не влезут, 40 % кадров будут -идти по 4 растра. +Итог семи позиций: **801 768 → 628 542, то есть −22 %**. + +### Достижима ли цель — арифметика на 2026-08-19 + +Цель: работа ≤ 430 000, тогда период станет 3 растра (хвост кадра — три +`gfx_wait_vsync`). + +- в ЛЁГКОЙ позиции снять надо **199 000**; +- в ТЯЖЁЛОЙ — **328 000**, и там уже 27 % кадров идут по 5 растров. + +Всё оставшееся в списке, кроме P13, даёт по оценкам **порядка 100 000** — и +это оптимистично. **Арифметика не сходится:** сцена с двумя персонажами, +чомпером и двумя факелами в три растра не укладывается без одного из трёх +решений: + +1. **P13** — переход на objtable и отложенные таблицы, как в оригинале + (единственный резерв нужного размера, но это переписывание слоя фона); +2. **осознанное расхождение с оригиналом** — например, не перерисовывать + передний слой персонажа, пока не изменились ни персонаж, ни тайлы под + ним (гейт по сигнатуре футпринта); +3. **принять 4 растра** как рабочий режим для сцен такой плотности и + выравнивать период, чтобы не было рывков 4/5. + +Решение за пользователем — это выбор между точностью порта и скоростью. ### Как воспроизвести сцену (важно для следующей сессии)