Android Jetpack Compose and GPU Overdraw: Painting a Performance Masterpiece !

Pranav Hadawale
7 min readJun 23, 2024

--

Introduction
Android Jetpack Compose has revolutionized the way developers build user interfaces for Android applications. It offers a declarative and modern approach to UI development, making it easier to create beautiful and responsive apps. However, like any powerful tool, Jetpack Compose requires careful attention to performance to ensure smooth and efficient rendering.

One common performance issue developers face when working with Compose is GPU overdraw. Overdraw occurs when the GPU draws the same pixel multiple times, wasting resources and potentially impacting the app’s performance. In this article, we’ll explore what GPU overdraw is, why it’s a concern, and how you can reduce it when using Jetpack Compose.

What is GPU Overdraw?
GPU overdraw happens when the GPU renders pixels that are subsequently covered by other pixels, meaning that the drawn pixels are not visible in the final frame displayed to the user. This unnecessary rendering consumes additional GPU resources, leading to increased power consumption and reduced battery life, especially on mobile devices.

Why is GPU Overdraw a Concern?
Excessive GPU overdraw can result in several negative consequences for your application:

  1. Performance Degradation: Overdrawing taxes the GPU, potentially causing frame rate drops and making your app feel sluggish and unresponsive.
  2. Increased Power Consumption: Unnecessary GPU rendering consumes more power, leading to reduced battery life and increased device heat.
  3. Visual Artifacts: Overdraw can lead to visual artifacts or glitches, affecting the overall user experience and the perceived quality of your app.

Identifying Overdraws :

Android Studio provides a built-in tool called Layout Inspector to visualize overdraw. Here’s how to use it:

  1. Enable Developer Options on your Android device, Search for “Debug GPU Overdraw” in Developer Options and select “Show overdra areas”.
  2. Open Layout Inspector and select your app’s running instance.
  3. Look for areas highlighted in red, pink, blue, green indicating overdraw.
  • True Color (No Highlight): This indicates no overdraw in that specific pixel. The pixel is only drawn once.
  • Blue (Overdrawn Once): A blue highlight signifies that a particular pixel has been drawn twice within the same frame. This might be due to overlapping UI elements or inefficient rendering.
  • Green (Overdrawn Twice): A green highlight signifies that a pixel has been drawn three times within the same frame. This suggests a higher level of overdraw and requires further optimization.
  • Pink (Overdrawn Three Times or More): Pixels highlighted in pink have been drawn four times or more within the same frame. This represents significant overdraw and requires immediate attention for performance improvement.
  • Red (Most Overdrawn): Areas highlighted in red are the most severely affected by overdraw. These pixels have been drawn the most number of times compared to other areas.

Strategies to Reduce GPU Overdraw in Jetpack Compose

Reducing GPU overdraw requires a combination of understanding your app’s rendering pipeline and applying best practices to optimize it. Here are some strategies you can employ to minimize GPU overdraw when using Jetpack Compose:

  1. Optimize Composable Hierarchie
    Avoid nesting too many composables unnecessarily. Each nested layer contributes to overdraw. Instead, try to flatten your composables hierarchy by reusing composables, using custom modifiers, or leveraging the built-in composables provided by Jetpack Compose.

Unnecessary Hierarchy

Reduced Hierarchy along with optimised Image Loading with remember

2. Use Efficient Composables
Jetpack Compose provides a variety of built-in composables optimized for performance. For example, use Box instead of nesting multiple Column and Row composables when positioning elements, as it reduces the number of composables and layers, thereby reducing overdraw.

Inefficient layout with nested Rows and Columns

More efficient layout with Box and Alignment

3. Remove Unnecessary Backgrounds
Evaluate your view hierarchy. Are there views with backgrounds that are entirely covered by other views? If so, consider removing those backgrounds or using a single background for multiple views.

Unnecessary Backgrounds

4. Lazy Layout
For long lists or scrollable content, leverage LazyColumn or LazyRow. These composables only render visible items, minimizing overdraw for off-screen elements.

This renders all product cards at once, regardless of whether they are visible on the screen.

For each product, the ProductCard composable is called only when the product is visible on the screen.

5. Optimize Custom Drawable
If you’re using custom drawables or graphics, optimize them to reduce the number of unnecessary pixels rendered. Use tools like Android’s Vector Asset Studio or third-party tools to create efficient vector graphics that minimize overdraw.

6. Reduce Transparency
While transparency can add visual interest, excessive use can cause overdraw. Consider alternatives like semi-transparent overlays or vector drawables with opacity settings.

Uses high transparency on the entire Column, potentially affecting all content

Sets a slightly opaque background color on the Surface for a subtle effect and removes the direct transparency applied to the Column before.

7. Be Mindful of Elevation
While shadows and elevation add depth, they can also contribute to overdraw. Use them judiciously and consider alternative ways to achieve visual hierarchy like :

  • Padding and Background Colors: Add slight padding and background colors to create a subtle separation effect instead of relying solely on elevation.
  • Stroke or Outline: Use stroke or outline effects to visually differentiate elements without introducing additional layers for shadows.
  • Z-Index: If essential, use Modifier.zIndex() to control the stacking order of elements and ensure properly obscured layers don't contribute to overdraw.

Excessive Elevation

Added a slightly opaque background color to the Column to create a subtle separation effect.

8. Clipping
Use the clip modifier to restrict the drawing area of a composable. This prevents unnecessary rendering outside the defined clip bounds.

9. Favor Stateless Composables
Stateless composables are generally faster to recompose and less likely to contribute to overdraw compared to stateful ones.

Stateful composable as isFavourite variable is remembered and mutable, meaning its value can change and persist through recompositions.

The isFavourite state is passed as an argument from a parent composable, making this function purely presentational.

10. Reuse Composable Logic
Break down your UI into reusable composables that encapsulate specific functionality. This promotes code maintainability and reduces the likelihood of redundant rendering.

ProductListItem builds the entire list item UI, including the image and text section. This might lead to overdraw if the background behind the list item content is drawn multiple times due to the nested layout structure.

ProductListItem now utilizes ProductImage and ProductDetails reusable components for the image and text sections. This allows Jetpack Compose to potentially optimize the rendering of each section independently, reducing overdraw. The background behind the list item content might only be drawn once, improving rendering efficiency.

11. Use derivedStateOf
derivedStateOf is a utility function that helps you create a state that depends on other states. It helps in optimizing recompositions by ensuring that the derived state only recomposes when the specific state it depends on changes, rather than the entire state object.

Using derivedStateOf ensures that the derived state only recomposes when necessary, optimizing performance

By adopting these practices, you can create performant and visually appealing UIs in Jetpack Compose that deliver a smooth and responsive user experience. Remember, optimizing for performance is an ongoing process, and these guidelines provide a solid foundation to get you started.

ENJOY COMPOSE !

--

--