GTLC全球技术领导力峰会·上海站,首批讲师正式上线! 了解详情
写点什么

Google 的 Android 性能模式

2015 年 1 月 10 日

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

渲染性能101 。这一系列视频的讲师是Colt McAnlis,据他介绍,不当的渲染是Android 上大部分性能问题的根源。如果一个Activity 需要16 毫秒以上的时间来准备在屏幕上渲染下一帧,系统将放弃这一帧。应用的用户会感觉滑动不流畅,或者变换有延迟,从而导致体验不好。McAnlis 推荐了很多用于检查此类问题的工具: Hierarchy Viewer Traceview 、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 工具提供的电量消耗详情来监控应用随时间变化的耗电情况。

查看英文原文: Google’s Android Performance Patterns

2015 年 1 月 10 日 10:165975
用户头像
臧秀涛 略懂技术的运营同学。

发布了 300 篇内容, 共 115.7 次阅读, 收获喜欢 23 次。

关注

评论

发布
暂无评论
发现更多内容

Kubernetes 将迎来首个 LTS 版本

倪朋飞

Kubernetes 容器 微服务

Graylog部署文档

蚍蜉

Linux 开源 工具 日志分析

回"疫"录(8):我怀疑我病了

小天同学

疫情 心理 回忆录 现实纪录 纪实

业务代码的救星——Java 对象转换框架 MapStruct 妙用

周三不加班

MapStruct 对象转换

字节流(InputStream/OutputStream)

Howe

Java 工作流

maven私服搭建

kcnf

maven

1分钟系列-Elastic Stack(ELK)简介

Yezhiwei

Logstash Kibana ELK

开源商业模式促进金融业科技生态的发展

fino星君

开源 金融科技

Python3.6.1官方文档练习——初入江湖(一)

Sicolas Flamel

Python python3.x 入门

《零基础学Java》 FAQ 之 1-HelloWorld程序发生了ClassNotFound错误怎么解决

臧萌

Java Hello World !

Redis学习笔记(字符串类型)

编程随想曲

redis

有节制的设计

胖鱼2号

微信 设计 無印良品

聊聊苹果账号的那些事儿

不要艾特我

iphone

快捷考勤打卡设置

Megatron7

ios

Java并发编程基础--volatile

Java收录阁

volatile 线程

《零基础学Java》 FAQ 之 2-Java版本那点事儿

臧萌

Java

取舍与可测试

孙苏勇

产品 产品设计 产品开发

Flutter引擎源码解读-内存管理篇

稻子

flutter ios android 跨平台 dart

理解 KL 散度的近似

Neil

人工智能 学习 Deep learning Machine Learning

一次生产事故导致系统崩溃的原因排查过程

hellocj

从删库到跑路?

岳老三

产品 职业 产品经理 职业素养 职业道德

python 之 「奶茶名字」的词云展示

Sicolas Flamel

Python python 爬虫 python教程

pip 配置路径要死记硬背?

风起帆扬了

Python Linux windows pip

【译】【UX】一个页面可以有多个面包屑导航吗?

Yukun

用户研究 UX 面包屑导航

从一道面试题来看计算机基础知识的重要性

周三不加班

数组 堆栈 函数栈 函数栈调用

Bash 的4种运行模式

Megatron7

bash Linux DevOps Shell

我们有来生吗?

Janenesome

读书 碎碎念 猎奇

书籍推荐

Reloaded

读书

css常见问题总结

靖仙

CSS css3

一次线上服务高 CPU 占用优化实践

张亚

性能优化 JVM cpu

利用goaccess分析nginx日志

Megatron7

nginx Linux

DNSPod与开源应用专场

DNSPod与开源应用专场

Google的Android性能模式-InfoQ