Performance Measurement

Rendering Performance -Android

Abhishek Jain
Tech Insider
6 min readApr 24, 2020

--

Most Mobile development is in a Mad Race 🏃🏿 towards getting features in, making perfect UI, and pushing features live in the market as soon as possible.

Application performance is only considered by developers when :

  • When QA notices laggy performance 🕵️‍♂️
  • End-user starts complaining 👈
  • Getting a high percentage of bad performance reviews 📑
  • Uninstall starts 😭
Google Android dev. Reaction

QA: Performance seems slow and laggy.

Developer: Ya, It’s Android’s problem, Android Guys need to tune it up.

Google Team: Oh My eyes, My EYES !!

So guys you cannot blame Android for bad performance of your app , you have to live up to your end of the bargain.

How do I know my app performance❓

( why I should review my code because every time I look at the feature created by me, looks awesome to me 😌 )

We will take the help of profiling tools because we can only optimize if we know how and where to optimize 🖥(Gather Information), Collect data and Analyze data and decide if the action required and then Take action on the problematic part of the code. We will discuss tools further in the article.

Do not over do — Decide if it is a problem, before moving on the optimization task , if it is not impacting your performance it’s not worth stressing your time or resource.

Slow rendering and Jank Story — 60 fps ⏳

why this 60 fps number is relevant ?

To ensure that a user’s interaction with your app is smooth, your app should render a frame in under 16ms (1000 ms / 60 frames) to achieve 60 frames per second.

If your app is running on average at 60 frames per second, and one frame takes much longer than the preceding ones to display, users will notice a break in smoothness that is called “lag” or “jank”. This 16ms number comes from phone’s hardware which defines how fast the screen can update itself in a second. Now, most devices update at 60 hertz that means you have 16ms to perform all your logic for each frame. If you miss that time window you get a dropped frame. (Try Profile GPU rendering speed tool in developer options for a visual representation of how much time it takes to render the frames relative to a benchmark of 16ms)

You miss the 16ms train, you invite Jank

Why Slow Rendering? 🤔

The Android rendering pipeline is broken up into two key sections the CPU and the GPU, both work together to draw images on the screen.

CPU Overhead: Display List is being built too many times during a frame or you are spending too much time on view hierarchy and needless redrawing.

GPU Processing Time: Wasting GPU time in overdraw (eg: coloring pixels that end up getting colored again later by something else)

How does your UI gets drawn to the screen?📱

or rather how does all that XML and markup language turns into pixels?

This is done with a process known as Rasterization, the process of taking some high-level objects like a string or a button or a path or a shape and turning it into pixels in texture on your screen.

Rasterization

UI objects like buttons or paths or checkboxes that are needed to be drawn on the screen are first converted to polygons and textures on the CPU and then passed off to the GPU to rasterize. CPU handles feeding these primitives to your GPU before it can draw anything on the screen. This is done through an API on Android known as OpenGL ES.

GPU isn’t that fast either so it makes sense to reduce the number of times you have to convert an object as well as the number of times you have to upload it for drawing. Thankfully the OpenGL ES API allows you to upload content to the GPU and then leave it there and see it when you’d like. The general rule of thumb is getting as much data on to the GPU as fast as possible and then leave it there without modifying it so that you save precious processing time.

View Rendering

Problem of Overdraw

Overdraw occurs when your app draws the same pixel more than once within the same frame. Suppose we have a bunch of backgrounds cards stacked over one another and the part at top hiding large portions of the cards that are hidden underneath, meaning that we’ll spend time drawing those cards which are invisible. To maximize performance in your application you’ll want to cut overdraw.

Visual Inspection Tool: GPU overdraw flag

On your android device go to Settings > Go to Developer options > Turn on GPU overdraw option. Android is using different colors to highlight areas of overdraw occurring on your screen.

  • Blue: Overdrawn 1 time 🙂
  • Green: Overdrawn 2 times 😲
  • Pink: Overdrawn 3 times 😟
  • Red: Overdrawn 4 or more time 🥴

If at any given point your app is drawing something that the user does not see, don’t draw it.

Simple Rules to have lesser OverDraws:

1. Remove Unnecessary backgrounds from XMLs.

Search for “android: background” in code, and for each background, determine whether it’s needed and visible on the screen.

eg : android:background=”@android:color/white”

2. Clip and redraw only areas of the screen that have changed.

For standard views, the Android system will reduce overdraw as much as it can and avoid drawing views that are completely hidden.

To address this problem in Custom views, the canvas class is equipped with a few special methods that you can use to tell the Android framework what parts of the canvas are hidden and don’t need to be drawn. The most useful method is canvas.clipRect, which allows you to define the drawable boundaries.

clipRect()

For complex custom views where you’re overriding the onDraw method, the underlying system doesn’t have insight into how you’re drawing your content, which makes it hard for it to know what to avoid. You can help the system by using Canvas.clipRect API. This function allows you to define a rectangle for a view, and only the stuff inside the rectangle will be drawn.

Now anything that partially intersects with the clipping rectangle will still be drawn, but on the GPU side, clipRect() will define an exclusion rectangle that allows the GPU on a per-pixel level to avoid coloring anything that’s clipped.

example:

// Save the canvas state.

canvas.save();

// Restrict the drawing area to only what will be visible.

canvas.clipRect( mCardLeft, mStart, mCardLeft + mCardSpacing, mCardHeight);

// Draw the card. Only the parts of the card that lie within the bounds defined by // the clipRect() get drawn.

drawCard(canvas);

// Revert canvas to non-clipping state.

canvas.restore();

References:

--

--

Abhishek Jain
Tech Insider

Android dev | Software developer at InMobi, Ex- MMT, Tokopedia