Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slow rendering of the most basic layout

Tags:

In my Android vitals 30% of my users experience slow rendering. My app has a pretty complicated UI so I made a really basic project to try to solve this problem. But it turns out it's pretty slow even with the simplest of layouts.

The layout is a centered text that Android studio offers as a template:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="slowrenderingtest.pichaipls.com.slowrenderingtest.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/timerView"
        android:text="00:00"
        android:textSize="40dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

The activity that uses the layout changes the text every second (because it's a timer):

Timer updateTicks = new Timer();
updateTicks.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Random r = new Random();
                timerView.setText(String.format("%02d", r.nextInt(60))+":"+
                                    String.format("%02d", r.nextInt(60)));
            }
        });
    }
}, 100, 1000);

When I turn on GPU profiling, this is getting pretty close to the 16ms limit for drawing each frame on some slower devices (apparently 30% of my users). Just one TextView. But here's the catch: when I first run the activity the rendering times are low but then they shoot up after a few seconds. If I keep touching the screen (there are no controls on the screen), the rendering times remain low. I'm guessing this is due to the CPU/GPU going to a low power state (so rendering takes longer).

My problem is the Android vitals. I keep seeing the warning about slow rendering times (I think anything above 5% of sessions experiencing slow rendering gets a warning) but I don't know how I can speed this up. And I'm worried it may affect my app's ranking but even with this really simple example far too many Android users have slow devices.

Can anything be done about this?

like image 844
TimSim Avatar asked Oct 22 '17 14:10

TimSim


People also ask

Which layout is faster in Android?

Results show that the fastest layout is Relative Layout, but difference between this and Linear Layout is really small, what we can't say about Constraint Layout. More complex layout but results are the same, flat Constraint Layout is slower than nested Linear Layout.

What is UI rendering?

UI Rendering is the act of generating a frame from your app and displaying it on the screen. To ensure that a user's interaction with your app is smooth, your app should render frames in under 16ms to achieve 60 frames per second (why 60fps?).

Which layout is better in Android Studio?

Use FrameLayout, RelativeLayout or a custom layout instead. Those layouts will adapt to different screen sizes, whereas AbsoluteLayout will not. Definitely right. I recommend RelativeLayout since it keeps the view hierachy flat.

How are layouts optimized?

To optimize layout performance, minimize the number of instantiated layouts and especially minimize deep nested layouts whenever possible. This is why you should generally use a RelativeLayout whenever possible instead of nested LinearLayout .


1 Answers

We're having the same issue is well and after some digging I suspect it's due the CPU getting idle?

Our case is similar. We have a Runnable inside which we update a TextView's text (only) every second using a Handler. The TextView resides on an item inside our RecyclerView. Interestingly, when we scroll the page, or there's some animation going on, or when interacting with the app (basically anything else other than the ticking), we get don't hit the 16ms mark. But let the device be idle and bam, each frame taking between 30-50 ms.

We tried different solutions mentioned in SO for similar situation. Like changing View's width from wrap_content to match_parent. Didn't help with the issue. We tried changing the 1000ms interval to 500, 200, 100, 50, 20, 16, 10 and only saw better results when using 16/10ms (CPU is constantly working?).

Found this article regarding CPU throttling. So probably when the CPU is idle, it's taking some more time to draw the frames?

If you look at CPU monitor in Android Studio, you'll notice CPU becomes idle as soon as nothing is happening. (Higher ones are when there's interaction, and using Nexus 5). enter image description here

But look the GPU monitor, that looks quite different from the Profile GPU Rendering bars on screen, no frames are actually crossing the 16ms mark! Not sure which GPU monitoring is the correct one. (Big yellow ones are when there's interaction). enter image description here

like image 152
Ahmadul Hoq Avatar answered Sep 22 '22 21:09

Ahmadul Hoq