Overdraw — це надмірне перемальовування одних і тих самих пікселів кілька разів за один кадр. Коли на екрані відображається складний інтерфейс із безліччю елементів, що перекриваються, GPU змушений обробляти кожен піксель багаторазово, що безпосередньо впливає на частоту кадрів і енергоспоживання. За даними Google Android Developer Documentation, 2025, зниження overdraw на 50% може збільшити продуктивність рендерингу до 30%. Оптимізація overdraw — обов'язковий етап при розробці додатків із плавною анімацією та чуйним інтерфейсом.
Головне
Overdraw — це ситуація, коли один і той самий піксель екрана перемальовується кілька разів протягом одного кадру рендерингу. В ідеальному сценарії кожен піксель має бути записаний рівно один раз, але в реальних інтерфейсах через вкладені View, фонові зображення та прозорі шари GPU виконує повторні записи.
Кожне додаткове перемальовування збільшує час рендерингу кадру. При стандартній частоті 60 FPS на обробку одного кадру відводиться приблизно 16,6 мс. Якщо overdraw призводить до перевищення цього ліміту, частота кадрів падає до 30 FPS або нижче, що помітно погіршує плавність інтерфейсу.
За даними Android Performance Patterns від Google, додаток із коефіцієнтом overdraw 3x витрачає втричі більше часу на фрагментний шейдер, ніж додаток з overdraw 1x. На пристроях з низькою продуктивністю GPU це призводить до відчутних лагів при скролі та анімації.
Для мобільних розробників розуміння overdraw критично важливе: саме цей фактор найчастіше викликає сіпаний скрол та низьку частоту кадрів у, здавалося б, простих екранах із великою кількістю вкладених елементів.
GPU-конвеєр складається з кількох етапів: вершинний шейдер, растеризація та фрагментний шейдер. Фрагментний шейдер — найзатратніша частина, оскільки він виконується для кожного пікселя кожного примітиву. При overdraw x2 фрагментний шейдер обробляє вдвічі більше пікселів, що безпосередньо збільшує час кадру.
Сучасні мобільні GPU, такі як Qualcomm Adreno та Apple GPU, мають механізми Early-Z Test та Hidden Surface Removal, які частково компенсують overdraw. Однак ці оптимізації працюють лише за певних умов, і покладатися виключно на апаратне прискорення не слід.
Наприклад, при рендерингу напівпрозорих елементів апаратний Early-Z неефективний, і кожен піксель обробляється повністю — overdraw у таких сценаріях може досягати 5x і вище.
Багатошарові фони — одна з головних причин overdraw у мобільних додатках. Коли Activity або ViewController встановлює фоновий колір, кожен вкладений View може додавати власний фон, і піксель перемальовується на кожному рівні ієрархії.
Дослідження Uber Engineering показало, що видалення надлишкових фонів у своєму Android-додатку скоротило overdraw на 32%, а час рендерингу екрана — на 25%. Аналогічна ситуація в iOS: встановлення opaque = true для непрозорих View виключає альфа-блендинг та запобігає множинному запису пікселів.
На платформі iOS overdraw часто виникає через використання прозорих UIStackView, CALayer з shouldRasterize та перекривних UIBlurEffect. Apple рекомендує перевіряти overdraw через Core Animation інструмент в XCode — він показує зони перемальовування у вигляді накладання червоного кольору.
Debug GPU Overdraw — вбудований інструмент Android, який забарвлює екран у різні кольори залежно від кратності overdraw. Фіолетовий колір означає 1x, синій — 2x, зелений — 3x, рожевий — 4x, червоний — 5x і більше. Ідеальний екран має бути переважно фіолетовим.
В iOS аналогічну діагностику виконує інструмент Core Animation у складі XCode Instruments. Він візуалізує зони перемальовування та показує точну кількість записів на піксель у режимі Color Blended Layers. Зелені шари — непрозорі (оптимально), червоні — містять прозорість і викликають overdraw.
Після діагностики важливо заміряти FPS до та після оптимізації. Різниця в 10–15 FPS при виправленні overdraw — нормальний результат для складного екрана зі списками та анімацією.
Видалення надлишкових фонів — найпростіший та найефективніший метод. В Android достатньо встановити android:windowBackground лише для Activity або теми, а не для кожного View. В iOS opaque = true для всіх непрозорих UIView знижує overdraw практично до нуля для цих елементів.
За даними Google I/O 2019, оптимізація overdraw в Google Maps дозволила знизити час рендерингу кадру на 40% за рахунок об'єднання шарів та використання ClipRect для обмеження області відтворення. Для Android розробників Google рекомендує наступні практики:
В iOS оптимізація досягається через налаштування CALayer: встановлення masksToBounds = true обрізає вміст за межами границь шару, а shouldRasterize вмикає кешування растрового представлення для статичних шарів.
Розглянемо практичні приклади на Kotlin та Swift, що демонструють типові сценарії усунення overdraw. Перший приклад показує оптимізацію через ClipRect в Android:
class OptimizedView@JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : View(context, attrs) {
override fun onDraw(canvas: Canvas) {
canvas.clipRect(
paddingLeft.toFloat(), paddingTop.toFloat(),
width - paddingRight.toFloat(), height - paddingBottom.toFloat()
)
// Draw content only within clipped area
super.onDraw(canvas)
}
}
Другий приклад — на Swift, показує вимкнення прозорості для шару, якщо елемент не повинен бути напівпрозорим:
class OpaqueLabel: UILabel {
override var isOpaque: Bool {
get { true }
set { }
}
override func draw(_ rect: CGRect) {
backgroundColor?.setFill()
UIRectFill(rect)
super.draw(rect)
}
}
Третій приклад — використання ViewStub для відкладеного завантаження карти в Android. ViewStub не рендериться до моменту, поки не стане видимим, що усуває overdraw на етапі ініціалізації екрана:
<!-- layout/activity_main.xml -->
<ViewStub
android:id="@+id/map_stub"
android:layout_width="match_parent"
android:layout_height="200dp"
android:inflatedId="@+id/map_container"
android:layout="@layout/map_fragment" />
// Inflate on demand
ViewStub stub = findViewById(R.id.map_stub)
stub?.inflate()
Часті запитання
Overdraw — це коли піксель на екрані перемальовується кілька разів за один кадр. Уявіть, що ви зафарбовуєте аркуш паперу, а поверх нього клеїте кілька прозорих плівок з малюнками — нижні шари доводиться перемальовувати щоразу, коли змінюється верхній шар.
Увімкніть Debug GPU Overdraw у налаштуваннях розробника. Елементи з overdraw 1x забарвлюються фіолетовим, 2x — синім, 3x — зеленим, 4x — рожевим, 5x+ — червоним. Оптимальний екран — переважно фіолетовий без червоних зон.
Кожне додаткове перемальовування пікселя вимагає виклику фрагментного шейдера, який обробляє колір, текстуру та освітлення. При 60 FPS на кадр відводиться 16,6 мс — якщо overdraw змушує GPU обробляти в 2–3 рази більше пікселів, ліміт перевищується і FPS падає до 30.
Так, безпосередньо. GPU, що виконує надлишкову роботу, споживає більше енергії. За даними дослідження Google, зниження overdraw з 4x до 1x зменшує енергоспоживання GPU на 35–50%, що особливо помітно на пристроях з дисплеями високої чіткості.
Для простих екранів — 1x–1,5x (фіолетовий з невеликою кількістю синього). Для насичених інтерфейсів — до 2x. Рівень 3x і вище (рожевий, червоний) потребує оптимізації. Google рекомендує не перевищувати overdraw 2,5x в середньому по екрану.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також