Браузер и фронтенд-рантайм
Render pipeline: спасение тормозящего списка
Читать про layout thrashing — не то же, что вытащить реальный список из него. Собери намеренно тормозящую скроллируемую ленту, профилируй её в DevTools и применяй порядок фиксов юнита — спрогнозируй стадию, исправь структурно, тянись к compositor в последнюю очередь — пока числа кадров не вернутся, с доказательствами на каждом шаге.
Преврати ментальную модель юнита в воспроизводимый инженерный цикл: профилируй pipeline, атрибутируй медленную стадию, убей forced sync layout, направь движение через compositor, защити границу GPU-памяти и подтверди фикс числами кадров до/после на реальном железе.
Возьми намеренно тормозящий скроллируемый список (свой или стартер из 5 000+ строк) и доведи его до устойчивых 60 fps на среднем Android — без пропущенных кадров при скролле, без предупреждений Forced reflow, число GPU-слоёв под 30 — доказывая каждый шаг измерениями DevTools, а не оценками.
- Таблица до/после: p95 длительность кадра, число пропущенных кадров, layout мс на кадр, composite мс на кадр и живое число слоёв — измеренные при одном и том же скролле, не оценённые.
- Ноль предупреждений Forced reflow while executing JavaScript в трейсе после при устойчивом скролле.
- Дорожка Frames в DevTools показывает зелёные (вовремя) кадры при скролле без красных пропущенных; p95 длительность кадра после — под бюджетом для целевой частоты обновления.
- Абзац-описание, называющий для каждого фикса, какую стадию он адресовал и почему встал именно туда в порядке фиксов (устрани forced layout, направь на compositor, пропусти внеэкранную работу, и только потом тюнинг).
- Добавь инструментацию LoAF и INP (PerformanceObserver для long-animation-frame плюс INP из web-vitals) и одностраничный on-call runbook: прочитай четыре сигнала, сопоставь каждый со стадией pipeline, примени лестницу фиксов, проверь.
- Добавь аудит passive: true — найди каждый слушатель scroll/wheel/touchmove, отметь действительно non-passive и покажи, что compositor-thread скролл восстановлен там, где preventDefault не нужен.
- Добавь gate Lighthouse CI на PR, который роняет сборку, если INP регрессирует выше 200 мс или CLS выше 0.1, и синтетический бенчмарк, диффающий p95 длительность кадра против ветки main.
- Перенеси CPU-тяжёлое вычисление на строку (например, рендер markdown или подсветку синтаксиса) в Web Worker и покажи, что main-thread полосы скриптинга уменьшаются, а скролл остаётся на 60 fps.
Это цикл, который ты запустишь в каждом реальном инциденте рендеринга: сначала профилируй, атрибутируй медленную стадию по цветам flame-strip, устрани forced synchronous layout через two-pass batch, направь движение через compositor с transform, пропусти внеэкранную работу через content-visibility, защити GPU-память, ограничив will-change, и подтверди числами кадров до/после на реальном железе. Сделав это один раз на тормозящем игрушечном списке, ты превращаешь production-спасение в мышечную память.