Профилирование GPU-рендеринга мобильного приложения
60 FPS на экране — это 16.67 мс на кадр. Из них CPU готовит команды рендеринга, передаёт их GPU, GPU рисует. Если GPU не успевает закончить к следующему vsync — кадр пропущен. Пользователь видит jank. Но где именно тормозит GPU — без профилировщика сказать невозможно: overdraw, слишком сложные шейдеры, огромные текстуры, некорректная работа тайлинга — причины разные и лечатся по-разному.
Инструменты GPU-профилирования
Android GPU Inspector (AGI)
Google Android GPU Inspector — наиболее мощный инструмент для мобильных GPU. Работает с Adreno (Qualcomm) и Mali (ARM). Требует устройство с поддержкой GPU counter profiling — большинство флагманов 2020+ поддерживают.
AGI показывает:
- GPU Counter — загруженность шейдерных юнитов, bandwidth, cache hit rate
- Frame Profiler — разбивка каждого кадра по draw calls, время на вершинный и фрагментный шейдер
- Memory — потребление VRAM, текстурный кэш
Критичная метрика — Fragment ALU utilization выше 90% при одновременно низком Primitive Assembly говорит: проблема в фрагментном шейдере, а не в геометрии. Упрощение шейдера или LOD-система — правильное направление.
Xcode Metal Debugger + GPU Frame Capture
Для Metal-приложений на iOS — GPU Frame Capture в Xcode. Захватывает один кадр и разбирает его по draw calls. Показывает:
- Каждый
MTLRenderCommandEncoderи его вклад в время кадра - Heatmap — какие пиксели рисуются сколько раз (overdraw visualization)
- Shader profiler — время выполнения конкретных инструкций шейдера, с указанием строки исходника
Для UIKit/SwiftUI — Core Animation Instrument в Instruments. Показывает CATransaction, offscreen-rendering passes (жёлтые слои в Debug → Color Offscreen-Rendered), layer composition.
Включаем Debug → Color Blended Layers в симуляторе: красные зоны — слои с alpha blending. Каждый красный пиксель рисуется дважды (или больше). На экране с 60% красного — реальная проблема для бюджетных устройств.
Профилирование на Adreno: Snapdragon Profiler
Snapdragon Profiler (Qualcomm) даёт самую детальную картину для Adreno GPU: L1/L2 cache miss rate, texture cache utilization, ALU стаки. Используем когда AGI не даёт достаточной детализации или нужна работа с Vulkan-приложением.
Что ищем и как правим
Overdraw. Developer Options → GPU Overdraw на Android, Debug → Color Blended Layers на iOS-симуляторе. Цель — минимум red/pink зон. Убираем лишние фоны у ViewGroup, устанавливаем opaque = true там где прозрачность не нужна.
Offscreen rendering passes. CALayer с cornerRadius + masksToBounds на iOS запускает offscreen render pass — рисует слой в отдельный буфер, потом composit на экран. На списке с 50 ячейками каждая с cornerRadius — 50 лишних offscreen passes за кадр. Решение: рисуем скруглённые углы через UIBezierPath в drawRect или через фоновое изображение с прозрачными углами.
Texture oversized. Текстура 2048×2048 для иконки 44×44 pt — GPU загружает лишние данные, тратит cache bandwidth. MTKTextureLoader с MTKTextureLoaderOptionGenerateMipmaps: true и правильным MTKTextureLoaderOptionTextureUsage для mipmapping — стандарт для 3D и сложных UI.
Кейс: 30 FPS на Adreno 650
Карточная игра на Unity: на Samsung S21 (Adreno 650) держала 30 FPS вместо ожидаемых 60. AGI показал: Fragment ALU utilization 98%, тогда как Vertex Processing — 12%. Фрагментный шейдер воды содержал 4 сэмплирования текстуры + нормал-маппинг + fresnel-расчёт. На мобильном GPU фрагментные шейдеры дороже вертикальных.
Решение: упрощённый шейдер воды для мобильной платформы (2 текстурных сэмпла вместо 4), fresnel аппроксимация через dot(viewDir, normal) без pow(). FPS вырос до 58–60 стабильно.
Сроки
GPU-профилирование и анализ — 2–3 дня. Оптимизация рендеринга по результатам — 3–10 дней в зависимости от сложности найденных проблем.







