[performance] Архитектурный аудит FPS и микрофризов: GPU instancing, объёмные эффекты и разделение simulation/render #126
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
🤖 Filed by Codex, AI-агент Владимира (chexit).
Проблема и границы доказанного
Владимир сообщает: Ryzen5600X + RTX3060, при налётах FPS иногда ниже40, частые микрофризы; раньше просадки были и на MacM5. Build/разрешение/trace конкретного сеанса не предоставлены. Аудит кода выполнен на AirDef
61aaa0bf359026711ba811a7f7e9877ce253ead2и Horizon278f356aa604fa21c2d15d0081823bbe0f891df25–6 ноября2026. Ни RTX3060, ни M5 в этой среде не профилировались. Ниже разделены доказанное устройство кода и архитектурные кандидаты, чью долю стоимости нужно измерить.Цель — системно уменьшить CPU/GPU frame time и spikes, сохранив качество/частоту/правила симуляции и визуальное качество выбранного пресета. Не закрывать задачу выключением записи/дыма, уменьшением числа целей, частоты20Гц, точности коллизии или простым увеличением fuel. DLSS/FG из #124 — отдельная помощь GPU, не лечение CPU-stall. RT #125 — отдельный режим, не оптимизация текущего HD.
Что уже есть — не начинать расследование с нуля
#9/#44 уже дали GPU pass timing и графический полигон. #26/#30 сократили часть поисков и строк; runtime передаёт модели по handles. #116 ограничивает очередь acoustic worker. RAID-STABILITY и #122 воспроизвели конкретный WASM fuel spike: полный обход height-cache на каждом взрыве заменён локальным удалением. В архиве max tick fuel уменьшился с300M trap до135.3M при том же лимите. Это не GPU/FPS и не доказательство причины текущих микрофризов. Actual WASM отчёты исключают host CPU/GPU, а frame hook стенда не является рендером. Статический hd_bench с несколькими позами также не заменяет бой с p99/frame-time trace.
Подтверждённые крупные пути работы в текущем коде
near.prepareиfar.prepareповторяют это для двух128×64×128 lattice; обе сетки заново заполняются в1024² atlas. Подготовка создаёт временные vectors/uploads. Фиксированный объём near/far grid не исчезает при уменьшении render scale; только последующий экранный fog дешевеет. Кандидат: sparse/dirty clipmap и GPU-подготовка, с сохранением плотности и каналов clear tunnel.fadeстановится0 после k>=0.28, но fbm raymarch6–14steps ещё выполняется для подходящих пикселей. После k>=0.55 нулевым становится и glow. Это статически видимая работа с нулевым вкладом; можно выделять фазы эффекта и прекращать такую работу без потери картинки. Это локальная часть большого плана, не замена ему.Архитектурные направления и порядок проверки
A. Постоянная GPU-геометрия моделей — первый крупный кандидат. Кэш model mesh/material по registry/resource/model generation, один upload на изменение ассета. Per-instance buffers: stableID, current/previous transform, light/material parameters и animation parts; GPU interpolation, batched instanced draws/indirect где поддерживается. Frustum/occlusion per camera, shadow-caster lists отдельно. Не потерять детали вне main view, видимые в shadow/reflection/offscreen views. Сохранить геометрические нормали #123, lighting, поворот шарниров, muzzle, outlines и resource reload. Считать bytes uploaded/frame и CPU bake/model/quad counts до/после.
B. Объёмный дым/эффекты как отдельная сцена. Общие immutable segment records, компактный clock и incremental updates вместо повторной полной упаковки. GPU age evaluation/binning либо sparse активные bricks/clipmaps с dirty/version tracking; сравнить стоимость этих вариантов. Работа только над областями с вкладом; сохранить итоговое sampling/свет/плотность/туннели, включая clear без видимого дыма. Инвалидация по camera snap, segment birth/death, возрастным изменениям, world/seek/cut. Избежать повторного CPU bake для near/far там, где данные общие. Нет права просто снизить grid resolution/MAX_SEGMENTS или убрать дальние следы.
C. Scene snapshots и разделение частот. Боевой state20Гц, render poses/интерполяция на кадровой частоте, неизменяемые scene snapshots и отдельные ordered event streams (#88). Static UI/status/catalog/model data пересчитываются по invalidation, не каждый tick; camera-independent data готовятся один раз, per-view только необходимое. Не рассчитывать live presentation, чтобы сразу выбросить её при replay, если можно безопасно отделить extraction от combat. Подтвердить выигрыш профилем; не объявлять native core SDK-free автоматически выполнением этого разделения.
D. Содержательная многопоточность, а не std::thread внутри гостя. Исследовать owned simulation worker/Wasmtime instance на native стороне: versioned world-input snapshot, input/command sequence, фиксированный tick, immutable output snapshots. Один поток владеет mutable combat state; render/game threads получают сообщения. Host world writes/queries, sound, UI, GPU выполняются владельцами соответствующих подсистем, а не из произвольного worker. Ограниченные очереди, cancellation/generation, отсутствие stale geometry при unload/seek. Визуальные snapshots можно coalesce, combat events/выстрелы/взрывы нельзя терять. Поток не имеет права «догонять» нагрузку пропуском симуляционных тиков; отставание явно диагностируется. Учитывать server-thread и in-frame пути.
E. Параллельные чистые задачи + детерминированный commit. Если профиль покажет CPU core bottleneck: пространственные индексы кандидатов/коллизии, переиспользуемые scratch arenas/ID indexes, версии мира для переиспользования горизонтов, чистые per-unit вычисления на immutable snapshot. Результаты принимать в стабильном порядке; общий RNG и порядок damage/target assignment сохраняются. Не размазывать mutable Sim между потоками mutex-ами и не менять решения из-за очередности завершения jobs. Ускорять поиск точного ответа, не заменять его грубой моделью.
F. Общие бюджеты очередей и native interop. Объединять dirty section/remesh/upload задачи по version, bounded queues для streaming/audio/render preparation и instrumentation backlog/age. Переиспользовать staging/upload rings; timeline/fence ownership без per-frame blocking wait/readback. Pipeline/shader compilation кэшировать/прогревать; startup и resource reload измерять отдельно. Capture readback/offline audio — отдельный режим, который не должен незаметно выполняться в live. Новая worker схема не повторяет снятие busy-guard из #116.
Измерения, которые делают аудит проверяемым
Сначала один воспроизводимый scene/record/seed и реальные terrain replies; фиксировать build+engine+driver/backend, resolution/scale, VSync, preset, monitors/grid, звук, запись и counts реально активных drones/missiles/models/smoke. Состав матрицы: idle → одиночный налёт → два перекрывающихся максимальных → взрывы/изменение чанков → плотный дым → monitor grid → replay/cut/export. Проверять факт принятия обоих приказов и полёт, а не прохождение сценария в ожидании unknown geometry.
Trace должен связывать: CPU frame/tick p50/p95/p99/max, host/guest wall-time и fuel отдельно, simulation phases, allocations/peak RAM, geometry bake/upload bytes, draw/instance counts, per-pass GPU timestamps, VRAM, worker queue length/age и pipeline compile events. Показать frame-time график и spikes, не только средний FPS. Архивные M5 Polygon/GPU и synthetic acoustic цифры не выдавать за новые измерения боевой сцены3060.
Для каждой большой переделки: baseline → один вариант → измерение на той же записи, затем следующий. Целевой frame budget определить для зафиксированного разрешения/пресета по baseline; не обещать «будет60» без замера. Главная цель — устранить длинные stalls и улучшитьp95/p99, а не увеличить счётчик presented FPS.
Обязательные инварианты и приёмка
Связано: #9/#44, #87/#88/#89, #102/#116/#122/#123; #124 (upscaling) и #125 (RT). Масштабная оптимизация может состоять из нескольких реализационных PR/подзадач; это issue фиксирует общий контракт и измеримый план, а не требует один гигантский rewrite-коммит.
🤖 Agent: Codex — дополнение по upstream Horizon, 6 ноября 2026; полное сравнение и план в #130.
Нашлись два конкретных небольших исправления, которые можно проверить раньше большой архитектурной переработки:
Дополнительно исследовать бюджетирование far-terrain результатов cb6a80698ce8d0207e4ffbf4b1a06e88fb22708a и освобождение arena pages вне render thread (#6687 upstream). Их upstream A/B не выдаётся за AirDef FPS.
Правки в рабочие файлы не применялись, объединённый клиент/эти backport не собирались и игровой A/B здесь не запускался. Для полной новой базы возникает отдельный блокер: upstream удалил WASM runtime, SDK и sandbox tests; прежние успешные native/WASM тесты текущего форка не подтверждают совместимость с этим Nightly.