From 952879e7fa960e2c7128d4b8fbe4a939877008b5 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Wed, 19 Aug 2026 17:17:27 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D0=B5=D1=81=D1=82=D1=80:=20=D1=82?= =?UTF-8?q?=D1=80=D0=B8=20=D0=BE=D1=82=D1=80=D0=B8=D1=86=D0=B0=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D1=85=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB?= =?UTF-8?q?=D1=8C=D1=82=D0=B0=D1=82=D0=B0=20=D0=BF=D0=BE=20=D0=BE=D0=BF?= =?UTF-8?q?=D1=82=D0=B8=D0=BC=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Записаны, чтобы не повторять, и с разбором причины. 1. cd_sig_same блоком (сравнение 10 байт циклом вместо 13 сравнений полей): по листингу короче (1939 -> 1290), на машине хуже 438 978 -> 450 426. Сумма тактов по листингу считает инструкцию один раз, а тело цикла исполняется десять раз. 2. cd_touch_pb (пометка «для блита» из file-scope вместо четырёх аргументов): 438 978 -> 442 242. В зелёной фазе блиты идут пакетным путём, где нужны все четыре значения, а в регистрах они дешевле, чем чтение из статиков. 3. Обёртка pop_cd_hit_slot поверх pop_cd_hit — 1799 против 1318 тактов; помогло только когда сравнение переехало внутрь. Общий урок записан там же: короткий листинг не равно быстрый код, и снятие аргументов со стека помогает не всегда. Co-Authored-By: Claude Opus 5 --- applications/PoP/docs/perf_registry.md | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/applications/PoP/docs/perf_registry.md b/applications/PoP/docs/perf_registry.md index aca2513..c9612ac 100644 --- a/applications/PoP/docs/perf_registry.md +++ b/applications/PoP/docs/perf_registry.md @@ -218,6 +218,38 @@ аргументами — стало ХУЖЕ (1799 тактов Z80 вместо 1318). Снимать аргументы со стека надо у того, кто их читает, а не этажом выше. +### Отрицательные результаты 2026-08-19 — НЕ ПОВТОРЯТЬ + +Три попытки подряд сделали ХУЖЕ. Общая ошибка в двух из них — я оценивал +правку по СУММЕ ТАКТОВ ИНСТРУКЦИЙ в листинге, а не по реально исполняемому +пути. + +**1. `cd_sig_same` блоком вместо тринадцати сравнений.** Снимок был +переложен так, чтобы сравнивать непрерывные 10 байт начала `pop_char_t` +циклом `do { if (*a++ != *b++) return 0; } while (--i)`. По листингу +функция стала короче (1939 → 1290 тактов), а на машине **стало хуже: +438 978 → 450 426 (+11 448)**. + +Причина: сумма по листингу считает каждую инструкцию ОДИН раз, а тело +цикла исполняется ДЕСЯТЬ раз. Тринадцать линейных сравнений выполняются по +разу каждое и выходят раньше на первом же расхождении. **Урок: короткий +листинг ≠ быстрый код; цикл надо разворачивать в уме.** + +**2. `cd_touch_pb` — пометка «для блита» из file-scope.** `pop_cd_touch` +зовётся из `pop_blit_b` с четырьмя аргументами, хотя тот держит те же +значения в `pb_x`/`pb_top`/`pb_w`/`pb_h`. Специализированный вход без +аргументов дал **438 978 → 442 242 (+3 264)**. + +Причина: в зелёной фазе блиты идут ПАКЕТНЫМ путём (`draw_tile` открывает +`pop_cd_batch`), а там нужны все четыре значения сразу — и в регистрах +(`x`, `y` приходят в HL/DE) они дешевле, чем чтение из статиков. +**Снятие аргументов со стека помогает не всегда: если значение и так живёт +в регистре, статик его туда ещё и загружать заставит.** + +**3. Обёртка `pop_cd_hit_slot` поверх `pop_cd_hit`** (описана в P16): +внутри всё равно звала функцию с пятью аргументами и добавила свои — стало +1799 тактов вместо 1318. Помогло только когда сравнение переехало внутрь. + ### P14. Fore-проход персонажа — от 4 122 до 117 570 [замеры 2026-08-19] **Самая НЕСТАБИЛЬНАЯ статья кадра.** Замеры на одной и той же сцене: