前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Performance in Android — Part 2

Performance in Android — Part 2

作者头像
用户9732312
发布2022-05-13 18:47:55
2790
发布2022-05-13 18:47:55
举报
文章被收录于专栏:ADAS性能优化

Welcome to the CPU side of the rendering pipeline

From the rendering pipeline point of view, the CPU is in charge of getting the XML files and turning them into something that the GPU can process in order to draw on the screen. This middle-object is a display list, an Android internal object that holds a list of GPU resident assets that might be needed, as well as a list of commands to execute with OpenGL in order to render it.

Display list — life cycle

The first time a View needs to be rendered, Android creates a display list for this View. This display list is used to draw the View on the screen so whenever we want to draw it again, we just need to send this display list to the GPU.

But sometimes the Views change on runtime so, is the same display list still valid if we modify some attributes? It depends. The answer is yes if we are modifying a property that doesn’t change the drawn content of the View, for example if we modify the position we can still use the same display list. However, if some visual part of this View changes like the background, the text or the size, the display list will be recreated in order to apply these changes to the final rendered object.

Is that all? Not really, the real problem starts to appear when we introduce complex layouts. You will understand it easier after this example.

代码语言:javascript
复制
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    ...
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        android:text="BUTTON"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        android:enabled="false"
        android:text="DISABLED"/>
</LinearLayout>

This layout roughly corresponds with image 1 (below). Imagine that we want to change the size of the enabled button to make it look like image 4 during the execution of the app.

Due to this change, we will need to recreate the display list associated with this button. Image 2 is how the enabled button looks after applying the new display list but as you can see, this change has “broken” our beautiful layout so now we would execute the display list for the disabled button after calculating the new position (we didn’t change the visual aspect of the button, so we can reuse it). After the display list is executed, we are in the image 3 and it seems that there is something wrong. The LinearLayout which is wrapping the buttons needs to be resized because its children don’t fit in the previous layout’s size. And yes, if you’re wondering if this means recreating the display list for the LinearLayout.

This is a dummy example of the implications of changing a View but imagine a change like that in a very complex layout where there are lots of nodes and the hierarchy is too high. All these changes would be applied on cascade and we might move out of the 16ms window. The Android rendering pipeline is really fast and it’s optimised to recreate and execute the display list, but even with that we should be careful with how we create the layouts.

To avoid this kind of problems we should create flat layouts without unnecessary layouts that don’t contribute to the final UI. This way we won’t loose time recreating and executing unnecessary display lists. Don´t misunderstand me, sometimes it will be needed and there is nothing wrong with that, but we should understand what it’s going on under the hood and try to optimise the process as much as possible.

How do I know if I need to restructure my layouts?

The best way to start is analysing our layouts with Hierarchy Viewer. This tool checks our app’s view hierarchy and it gives us relevant information about how long the measure, layout and draw steps take in relation with other views.

For those who have never used this tool before or want to go a bit further, there is a walkthrough on the Android developers site that I recommend before continuing reading this post as I will focus more on the information that we can gather and I’m not going to explain how to use the tool in details (please leave me a comment if you think I should). And before start, I just want to remember that for using this tool is needed to setup some configuration depending on the device version (you can find how here).

Hierarchy Viewer, I choose you!

There are a lot of useful information that we can gather from Hierarchy Viewer about our views, but because we are trying to solve a very specific problem we just need to focus on two things: the Tree View (or Tree Overview) and the information displayed when when we click on a node.

The Tree View represents all the hierarchy for our screen in a tree form, where each node is a View on our layout. This view is really useful because it gives us an open perspective of how complex is our layout. Our goal is to have this tree as shallow and flat as possible, so we can easily identify where the problems can be just with a quick look.

Focusing now on a node, when we click on one of them we will see information about a view in particular like the class, the ID, a preview, etc. But the relevant information for us are the ones marked in the red square on the image. This two components give us the absolute (numbers) and the relative (represented with dots) time spent on each of the Measure, Layout and Draw phases for this specific node.

As you know, we need to connect our device in order to run the Hierarchy Viewer. This is because Hierarchy Viewer takes all the information from a running app. So the absolute time is actually the absolute time that the device needed to perform theses actions for this particular node. This information probably will change if we reanalyse the screen and don’t be scare if this happens. The reason for that is because the devices’s CPU might be doing some other stuff and be more or less overloaded, so it can take more o less longer.

But what should be interesting for us are the relative indicators. These three dots tell us the relative performance of this node in respect to all other profiled nodes. The colours of the dots can change between:

  • Green means the view renders faster than at least half of the other views.
  • Yellow means the view renders faster than the bottom half of the other views.
  • Red means the view is among the slowest half of views.

A red node is a potential problem in any situation where we wouldn’t expect slow performance, for example in a leaf node. Now, you might find confusing this assertion but, we are always going to have red indicators on our layouts, and this is not necessarily bad. In our layout something has to be the slowest node and because this indicators use relative time, the slowest node will be marked as red. So the question is, is it the node that we are expect to be the slowest one?

Facing nasty layouts

we can find some advices that will help us to know if we should refactor our layouts or when we should take a look at them:

- Look for red dots in leaf nodes or view groups with only a few children. This might point to a problem. Your app may not be slow, or it may not be slow on your device, but you need to be aware of why that dot is red. Systrace or Traceview can give you additional information.

- If you have a view group with many children and a red measure phase, take a look at the children to see how they are performing.

- A view with yellow or even red dots might not be performing slowly on the device. That’s where the actual numbers are helpful. Systrace or Traceview can give you additional information.

- If the root view of a hierarchy has a red measure phase, red layout phase, and yellow draw phase, this is somewhat typical, because it’s the parent of all the other views.

- If a leaf node in a tree with 20+ views has a red draw phase, this is a problem. Check your OnDraw method for code that shouldn’t be there.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android性能优化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Welcome to the CPU side of the rendering pipeline
  • Display list — life cycle
  • How do I know if I need to restructure my layouts?
  • Hierarchy Viewer, I choose you!
  • Facing nasty layouts
相关产品与服务
GPU 云服务器
GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于生成式AI,自动驾驶,深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档