微信号:infoqchina

介绍:有内容的技术社区媒体

Google的Android性能模式

2015-01-16 12:03 InfoQ


Google开发者YouTube频道发布了探讨Android性能模式的16个视频, 列出了开发者在创建应用时容易出现的一些性能问题,同时提供了很多处理建议。本文是对这些问题和建议的总结。


渲染性能101这一系列视频的讲师是Colt McAnlis,据他介绍,不当的渲染是Android上大部分性能问题的根源。如果一个Activity需要16毫秒以上的时间来准备在屏幕上渲染下一帧,系统将放弃这一帧。应用的用户会感觉滑动不流畅,或者变换有延迟,从而导致体验不好。McAnlis推荐了很多用于检查此类问题的工具:Hierarchy ViewerTraceview、Profile GPU Rendering、Debug GPU Overdraw和GPU View Updates。


建议尽量减少失效(invalidation)和布局(layout)的数量。前者可以用Developer Option Show GPU View Updates可视化地观察,而后者可以使用Hierarchy Viewer来分析。


过度绘制过度绘制衡量的是一个特定的像素在一帧中被绘制的次数。当然这个值最好是1, 但有时候并不是这样。Debug GPU Overdraw这款工具可以显示重绘最多的区域,所以开发者就知道要优化什么了。


VSYNC开发者应该注意帧率变化,尤其是当帧率从高于屏幕刷新率突然掉到低于屏幕刷新率时。这会导致动画出现延迟,用户很容易感知到。


Profile GPU Rendering从Developer Options设置可以访问这个工具,它能够从屏幕上活动的所有Android Activity生成性能图,这些Activity通常包括通知和导航条,再就是活动的应用。一帧的时间在16毫秒以下为宜。性能图会包含所有和渲染相关的主要活动的计时信息,这些活动包括更新显示列表、执行显示列表和处理glSwapBuffers。


60 fps要让人眼对复杂动画有不错的感受,帧率最少要达到60 fps。保持60 fps的帧率并避免变化很重要。


定制视图有些过度绘制优化,比如不去绘制完全被遮盖的组件,但是当为了创建定制的视图而覆盖onDraw()方法时,渲染过程可能会缺少这样的优化。为尽量减少过度绘制,建议使用canvas.clipRect()来指定定制绘制的精确区域。此外,应该使用quickReject()来确定某个区域是不是在剪掉的矩形之外,如果没有必要,应该避免浪费时间绘制这个区域。


内存搅动为大量很快就会被丢弃掉的小型对象重复分配内存,会致使垃圾收集器多次介入,如果这些时间正是在16毫秒的窗口绘制时间内,可能会导致丢帧。借助Android Studio Memory Monitor,开发者可以将垃圾收集活动以可视化方式显示出来,并确定是否有过多的垃圾收集。之后可以利用Allocation Tracker来确定这些内存对象从何而来。然后修复可能导致问题的相关代码,从而避免某些内存分配,或者是把这些分配移到循环之外。此外,对象不应该在onDraw()内分配,因为这个方法1秒会调用很多次。如果应用确实需要大量很快就要丢弃的对象,建议使用对象池,一次创建,多次复用,从而避免垃圾收集。


内存泄漏。内存泄漏使垃圾收集消耗的时间变长,这又会影响帧率。为确保在用户离开某个Android Activity之后,不会出现内存泄漏,McAnlis建议创建一个不需要消耗内存,或者只需要消耗极少内存的空Activity,转到这个空的Activity并强制执行一次垃圾收集。建议在转移之前和之后,使用Android Studio中的堆和分配跟踪工具来确定这个Activity是否有内存泄漏。


电量消耗根据普渡大学和微软的一篇研究论文(PDF),大约70%的电量是被第三方广告模块消耗的,它们会执行数据分析、位置发现和广告下载等操作。只有30%的电量是应用中实际活动消耗的。Google建议开发者仔细处理电量消耗问题,因为这是用户最关心的。最重要的建议是,除非绝对必要,不要将设备从睡眠中唤醒。如果必须唤醒,建议使用 WakeLock,并设置一个超时时间,以确保如果应用出现问题,设备可以回到睡眠状态。另一个思路是使用AlarmManager.setInexactRepeating() ,将唤醒操作和另一个活动结合起来,从而节省电量。


可以将某些CPU密集型操作推迟到连上充电器并连接到WiFi时,或者将多个工作组合到一次唤醒操作中。这可以借助JobScheduler API,它支持将某些工作延迟一段时间。还有一个建议,要小心地使用网络连接,因为在发送完一个网络请求和接收到一个响应之后,设备要保持至少5秒钟的唤醒状态,以备从服务器传过来的另一个数据包。


McAnlis还建议利用Settings|Battery和Battery Historian 工具提供的电量消耗详情来监控应用随时间变化的耗电情况。


您可以点击“阅读原文”,跳转至网站,观看相关视频(需科学上网)。



 
InfoQ 更多文章 Facebook如何实现PB级别数据库自动化备份 学术派Google软件工程师Matt Welsh谈移动开发趋势 Spotify为什么要使用一些“无聊”的技术? 妹纸们放假了,汉纸们做啥? 大多数重构可以避免
猜您喜欢 从零开始的Android新项目(1):架构搭建篇 事件监听器 学习Python的五大理由 58同城前后端分离开发模式实践 设计是门逻辑学,然后才是美学