#翻译# Android Performance Case Study by Romain...

片头声明:
一、本片是据Romain Guy剧本编写Android Performance Case Study衍生的电影,某些部分可能因为我的英语水平有限及理解缘由,可能有别于原做者的原意。若有发现,请指正。以利于咱们共同窗习,共同进步。
html

二、本片是继Android性能优化案例研究(上)  by孙立出的下版。狗尾续貂,望你们海涵。

剧情介绍:孙立翻译的上半部分是如何发现性能问题,我这的下半部分是如何使用工具肯定这些问题并给与了部分问题的解决方案。对于上部,就再也不这里转载了,能够直接点击上面连接进行阅读学习。也可能过几天会转载过来
android

各位看官,下面就接上部开播:

移除无用的图层:为了减小重绘,咱们首先必须知道,什么会致使重绘。这也是Hierarchy Viewer和Tracer for OpenGl以前的用处所在。

Hierarchy Viewer(图层查看器)是ADT的一部分,能够用于检查View Hierarchy(视图层级)的快照。它在解除布局问题时尤为有用,但也能够方便的检查工做性能。

【重要:默认状况下Hierarchy Viewer只能工做在非安全模式的设备上,好比工程机、平板或者虚拟机。要在全部手机上使用Hierarchy Viewer,须要添加一个叫ViewServer的开源库项目到你的应用中。
https://github.com/romainguy/ViewServer】


在ADT(或者监视器)中打开Hierarchy Viewer视图,而后选择Windows tab。(粗体高亮现实的窗口就是手持终端的foreground设备,通常也就是你要检测的那个界面)。点击高亮显示的条目,而后点击在工具栏中的Load按钮。(它看起来想一个蓝色方块树。)而后耐心等待载入整个树。当这该视图树载入完毕,你将看到以下图类似的画面。【译者:最好使用Monitor,译者屡次使用ADT老是出错。】


    如今,View Hierarchy已经在工具中载入成功,咱们能够将其做为一个图片文档导出。只要点击工具栏中的第二个按钮(工具提示为:Capture the window layers捕获窗口图层)。Adobe Photoshop不是必须的软件,可使用与其兼容的工具,好比Pixelmator,GIMP等等。能够下载我生成的PSD文件

    这个图像文件展现了应用中在一个Layer(图层)的每个View。每个layer(图层)基View.getVisibility返回的数据,分别被标记为可见或者不可见的。每个layer(图层)使用View 可用android:id或者它的类名来命名。我开始添加支持组件来重建视图树,我应该完成这个功能。
     经过检查这一系列图层,咱们能够快速认出至少一个资源的overdraw,多个全屏背景。第一个就是这第一个layer。称为DecorView。这个视图被Android生成并包含了在主题中的特殊背景。在应用中这个默认梯度(默认透明度)是不可见的。所以能够安全的将其移除。
滚动DecorView你能够看见一个LinearLayout包含了另一个全屏梯度(透明)背景。它与DecorView的背景是彻底同样的,所以,它也是不须要的。惟一可见背景必须保持,它就是命名为id/tweet_list_container的视图。

【移除窗口背景:定义在你主题中的背景 被系统用来在启动的你应用以前做为预显示窗口。千万不要将其设置为null除
非你的应用是透明的,相反,应该设置一个你认为好的颜色或者图片,或者在onCreater()方法中调用getWindow().setBackgroundDrawable(null)来将其去掉】。 git

进一步的减小overdraw
经过图像文件,咱们能够很容易明白应用是怎么生成的。可是它对于移除小区域的overdraw就显得十分吃力。那咱们就须要打开Tracer for OpenGL。在ADT或者Monitor中名字为Tracer for OpenGL的视图,在工具栏中点击箭头那个图标。输入你应用的包名和主Activity的名字,而后选择存放位置(destination File)点击trace按钮。

【建议:OpenGL检测可能很大而且能够真正减速获取图像。 为了让它更小,获取图像更快,不要复选Data Collection Options boxes框。】

github

【Activity名字:当你打开应用后,logcat将显示包名和Activity名字。根据这个你就能够晓得在Tracer for OpenGL中要输入什么东东了。】

当应用已经打开并运行,使可用前两个选项:
* Collection Framebuffer contents on eglSwapBuffers()
* Collection Framebuffer contents on glDraw*()
第一个选项对于快速找到你感兴趣的frame十分有用,然而第二个选项则容许咱们经过绘制命令查看每一个frame生成使用的命令。第二个选项是解决overdraw 问题的关键所在。

开启这两个选项以后,我开始滑动主界面的时间轴。它将花费至关长的时间来获取每个frame(不出意外的话,须要30秒)。所以我建议你下载我获取的文件(http://goo.gl/yPjB5)。你能够在Tracer for OpenGL中点击第一个按钮打开这个文件。

加载完毕后,视图展现你每个发送到GPU的GL命令为一个frame快照。若是你下载个人文件。跳到21Frame处。当一个frame被选中以后,你能够在Frame Sunmmary tab 页中查看它是什么样子的。另外,你能够点击绘制命令,将其蓝色高亮,在Details tab页中查看这个frame的当前状态。

【总结:GL 命令被经过View分组。他们从新建立你在HierarchyViewer或者xml Layout文件夹能够看到的树。这使它很容易就能理解什么View产生了一个什么样的特定操做。】

经过连续点击前三个绘制命令,你能够看出已经在Photoshop中肯定的问题,一个全屏的背景被绘制了三次。

咱们经过查看下载的Tracer,能够发现更多能够优化的地方。当一个tweet(listitem)被绘制,一个ImageView被用于绘制头像(原文是:avatar)。ImageView第一次绘制了一个背景而后绘制头像(avatar)自身。



若是你仔细看,你将会发现背景只是做为图片的一个边界。这意味着,这意味着在头像图片中间的这黑色部分被
overdraw了。这片9path已经被头像图片(avatar)彻底覆盖了。



web


一个对于这个问题的简单修复办法是使这中间可拉伸的9-patch图片透明。Android的2d渲染器优化9patches的透明部分。这个简单的改变将会移除一小部分的overdraw。

有趣的是,一样的问题也出如今了内联媒体(inline media)中。头像图片(Avatars)图片十分小,因此他们overdraw不会致使大的消耗。可是内嵌媒体(inline media)可占据屏幕至关大的一部分区域。问题的修复与上面的方法一致。



【深度优化:我更但愿Android的2d渲染管道有能力自动正确的为你overdraw。咱们已经有了些想法,可是我还不能作出任何关于这方面的承诺。正像加入GPU优化,这只能做用于不透明的元素。】

扁平化视图( 正则表达式

Flattening the view hierarchy):


好的,如今咱们已经对overdraw(大部分都是)关心过了,如今让咱们回过头来再看看Hierarchy viewer。经过检查图 像树,咱们能试图肯定不须要的Views。移除Views特别是ViewGroup,这不只能够提升帧速率,并且还能够减小内存消耗 ,启动时间等等。
快速查看Falcon Pro视图层级,你能够肯定有几个ViewGroup和一个单独的子视图。这些ViewGroup通常都是不须要而且 很容易移除掉。下面展现的图片中至少最后面的两个节点是能够移除的。

也有一些另外的视图能够从这个树中移除。好比,每个tweet都包含了一个命名为listElementBottom的 RelativeLayout。这个Layout包含了做者的名字,他的Twitter,从tweet发送出来以后已通过去的时间。名字和handle是 两个分离的TextView代替了单独一个TextView加入多种类型不一样的spans,时间和icon使用一个TextView和一个 ImageView能够被结合称一个单独的TextView,查看TextView's compound drawables   


左边的菜单使用了多个LinearLayout+TextView+ImageView的组合来展现标签和图标。其实每一个可使用单独一个 TextView就能够代替了。

【如何扁平化你的UI:我解释了不少关于这方面的技术。你能够去看我在2009 Google I/O Talk


关于“输入”事件:记不记得当咱们查看systrace而且发现,当处理触摸事件的时候会有些卡顿?如今,是时候来追踪这个 问题了,traceview是咱们去明晰系统正在作什么的最好工具。

Traceview是一个记录应用在调用某个方法花费多少时间的虚拟机分析器。能够在ADT的DDMS视图或者monitor中启动他, 在Devices tab中选择你应用进程,而后点击Start method profiling按钮。红色环绕的三个箭头。
在开启追踪以后,我来回滑动主时间轴,而且从新点击按钮来结束trace。你也能够下载个人追踪记录:
结果以下图截屏所示。


点击第#21,ViewRootImpl.draw().高亮绘制时间。表格中最后一行给你一个这个方法的和在它的子类里平均的调用时间 。如你使用高亮来仔细看这时间轴,你将会注意到在连续frames之间的间隙。

一个最简单找出这些在这些间隙中到底发生了什么方法就是(选择他们其中一个的开始部分进行放大,而后点击你能发 现的最大色块)你追踪父子链(parent chain)直到找到你能够辨识出来的东西。在个人例子中,我追踪一个花费了平 均时间的0.5ms的叫Patter.compileImpl,直到全部都指向了DBListAdapter.bindView。

显然每次一旦有新的item被绑定或者滑动主时间轴时,应用都会从新一遍一遍的编译这相同的正则表达式。Traceview展 示了绑定一个View平均花费38ms而且有56%的时间花费在解析HTML文本上。这看起来某些东西能够被能够在后台实现而不 是阻塞UI线程,正则表达式不该该每次都要从新编译。


接下来看你的了!
我留下最后一个trace做为练习。这个应用在两边有两个菜单,能够经过敲击时间线的左边或者右边来显示。(在显示这 菜单时GPU overdraws 高亮了过分绘制的部分,我已经使用Tracer for OpenGL来获取了这个问题的几帧。下载个人 trace而后看看你是否能找到什么致使了overdraw(做者提示go to frame #34)。

提示就不翻译了: Hints: the application should use hardware layers by calling View.setLayerType() to simplify drawing.  There are also extraneous backgrounds that can be optimized away with clever use of 9-patches. Clipping  could also be very helpful. Finally, maybe a ColorFilter set on a Paint passed to setLayerType() could  help remove the last drawing command.


我已经展现了多种你能够用于优化你的应用的工具。我已经花费了大量的时间来描述在这些工具的帮助下,使用什么技术去解决已辨别的问题。可是这个文章将会转到一本书中。检出文档这官方文档( Android developers web site)引用和全部GoogleI/O Android talks.
                                                                                                          ---Romain Guy 安全

【后语:最好使用Monitor,鄙人在使用ADT的时候老出错。 性能优化




补Traceview操做图:



session

app

相关文章
相关标签/搜索