App架构师实践指南四之性能优化一
App架构师实践指南四之性能优化一
1、性能维度
常见用来衡量App性能的维度如图9-1所示。其中,性能指标包括电池(电量/温度)、流量(上行流量/下行流量等)、CPU(平均/最大/最小)、内存(平均/最大/最小)、帧率(平均/最高/最低/页面切换)和crash率等。
2、App优化总结描述
---倾听用户意见。了解并听取用户的意见是成功最好的工具之一,用户的意见既包括发布前的意见,又包括发布后的意见。
---衡量、分析用户行为并作出响应。衡量用户行为是发现并解决问题的最佳方式之一,我们可以通过统计分析用户行为来定期衡量与用户相关指标(如下载源、留存率、应用内行为等),从而对流失点、低评分、卸载率高等问题进行处理。
---提高稳定性并消除错误。可以借助Monkey等工具对APP稳定性进行测试,来消除可能存在的错误。
---改善UI响应能力。UI的卡顿会直接导致用户的流失,这是我们需要关注和优化的。
---提升可用性。可用是APP功能最基本的要求,我们可以通过线上演练和用户反馈等方式进行测试验证。
---专业外观和美术设计。UI设计是APP必不可少的一环,设计师的存在是保证我们界面优雅美观的基础。
---合适的功能。功能并不是越多越好,适时做减法,抓住属于我们APP的核心功能才是最重要的。
---与系统和第三方应用集成。Home界面的小部件(如天气类应用等)、丰富的通知、全局搜索等第三方应用集成可以进一步提高用户满意度,可以使用户享受应用和设备之间的无缝使用体验,值得考虑和关注。
3、性能测试平台
如果对自家数据不敏感,可以尝试采用第三方性能测试平台进行性能测试,主流性能测试平台有百度MTC,腾讯GT、bita以及Bugly,阿里云效,科大讯飞iTest,网易Emmagee,华为DevEco、Testin等。
4、硬件性能优化
硬件性能指由硬件或软件引起的导致电池消耗的性能,具体包括屏幕、传感器、CPU、WakeLOCK、JobScheduler等耗电性能。
4.1电量信息获取
---通过手机系统文件。直接通过手机系统文件“/sys/class/power_supply/battery/uevent”来获取手机电量相关信息(包括手机的电流、电压、电量和温度信息),这是一种简单暴力的方式,虽然存在一定的适配问题,但有时候也是最有效的一种方式。
---CPU分析。对于CPU过高使用导致的耗电,最简单直观的方式是通过top命令实时查看各个线程的CPU占用情况,如果某个线程持续占用超过10%就要重点关注了。(top命令需要借助ADB Shell,如果无法直接使用top命令,可以通过ANR的traces.txt文件进行分析,文件中线程里的schedstat表示线程消耗CPU的情况)。
---Batterystats工具和Battery Historian脚本。
------概述。基于Batterystats工具,通过adb命令dump出电量使用的统计信息,再通过Battery Historian脚本分析呈现dump出的统计信息文件。
------使用条件
----------Android 5.0+(API 21+)
----------Phython/Go语言环境。Battery Historian是Google开源的历史数据获取工具,基于Go语言开发,基于Phython环境运行脚本historian.py或者基于battery-historian.go来分析。
---使用
----------下载安装Battery Historian并配置好环境。
----------adb重连手机设备(通过adb kill-server和adb devices)。
----------reset电池收集信息,(adb shell dumpsys battery stats - reset)
----------断开手机设备连接,操作我们待测的App。
----------重连手机设备,dump出电量使用统计信息,存储到batterystats.txt(adb shell dumpsys battery stats > batterystats.txt)
----------将数据转换成可查看到html形式(python historian.py batterystats.txt > batterystats.html)
----------Battery Historain新版本中建议通过bugreport方式导出数据,这样可以看到更多信息。这种方式需要使用Docker或者配置Go语言环境,然后运行Battery Historian,再导入bugreport文件呈现电量使用信息。其信息非常丰富,如图9-2所示。
(1)adb bugreport bugreport.zip(Android 7.0+)
(2)adb bugreport > bugreport.txt(Android 5.0~6.0)
说明:上面描述的是图形化展示方式,如果仅仅只需要获取电量信息,可以直接使用命令adb shell dumpsys batterystats,打印出来log中即有电量信息,Android 5.0中信息比较粗糙,Android 6.0+中有更细化的耗电量信息。
-------耗电量统计API.
Android系统耗电量统计API一直存在,只不过都是隐藏的。Android系统中的设置-->电池功能调用的就是这个API.
------ GSam battery Monitor。检测手机电池电量消耗去向,以折线图进行统计展示。手机需要root,应用需要获取root权限。
5、耗电分析
耗电量计算
---Android中手机自带的设置中有电量统计,其本质是通过Android Framwork层中专门负责电量统计服务的BatteryStatsService来实现的,其在ActivityManagerService中创建,代码如下:
mBateryStatsService = new BatteryStatsService(new File(systemDir,'batterystats.bin').toString)
其他的模块比如WakeLock等向BatteryStatsService喂数据,数据存放在系统的batterystas.bin文件中,再交于BatteryStatsImpl来进行电量数据的分析,然后可以通过processAppUsage和processMiscUsage方法计算具体耗电量,系统的设置据说这样得到电量统计信息的。
如何来衡量一款App是否耗电,其实并没有统一标准,我们进行电量测试也仅仅是对移动设备电量消耗快慢的一种直观感应。一般用平均电流来衡量电量的消耗速度,但具体多大的平均电流值可以被认为是耗电呢?可以参考腾讯Bugly团队的一种定义方法,如图9-1所示。
手机中的耗电大户/主要耗电场景
---手机屏幕。毋庸置疑,手机中最耗电的模块肯定是屏幕里。亮屏时间越长,电量消耗越快。
---CPU相关。复杂运算逻辑、无限循环等会直接导致CPU负载过高,耗电剧增。
---网络相关。一般情况下,网络相关(网络请求、数据传输、网络切换等)是仅次于屏幕等耗电大户。
---WakeLock(Android)。WakeLock是Android系统中用于优化电量使用情况等一种手段,通过在用户一段时间没有操作的情况下让屏幕和CPU进入休眠状态来减少电量消耗。一些应用中出于特定业务场景调用PowerManager.WakeLock来使CPU保持持续运转,而释放需要时间,甚至呢根本就忘记释放了,灭屏后CPU却还在一直运转着,从而大大增加了耗电量。
---GPS。GPS定位涉及GPS位置传感器,也是耗电大户。平时不使用时应该关闭。
---Camera。Camera涉及前后摄像头硬件,如果一直使用(录屏等),耗电也会非常可观。
6、电量优化
电量优化最佳实践
6.1 网络相关
6.1.1发起网络请求时机。业务区分当前网络请求时需要及时返回结果的(用户主动下拉刷新等),还是可以延迟执行的(异步上传数据等),可以延迟执行的有针对性地把网络请求行为绑定在一起发出。
6.1.2减少移动网络被激活的时间和次数。
---采用回退机制来避免固定频繁的同步请求,例如,在发现返回数据相同的情况下,推迟下次的请求时机。
---使用Batching(批处理)的方式来集中发出请求,避免频繁的间隔请求,例如同一业务尽量少使用多次请求,合并多次请求。
---使用Prefetching(预取)的技术提前把一些数据拿到,避免后面频繁再次发起网络请求。
6.1.3数据处理
---网络数据传输前进行压缩处理
---进行大数据量下载时,尽量使用GZIP方式下载。
---使用高效率的数据格式和解析方法,推荐使用JSON和Protobuf。
6.1.4慎用或禁用Polling(轮询)的方式去执行网络请求,Android可以采用Google Cloud Messafeing,ios可以采用APNs。
6.1.5减少推送消息次数和频率。App收到服务端大量或频繁的推送消息,对手机的耗电量一定会有影响。
6.1.6网络状态。处理具体业务前,养成判断当前网络状态的习惯和编程思维。例如,在移动网络下,减少数据传输或降低数据传输频率(Wi-Fi下网络传输耗电量远比移动网络少);在网络不可用状态下,尽早进入网络异常处理逻辑,避免不必要的运算逻辑等。
6.2 界面相关
---离开某个界面后停止对应的耗电活动。例如,用户离开了A界面,而对应的耗电活动并没有及时停止,就会造成资源浪费。
---应用进入后台禁止异常消耗电量。
6.3 定位相关
---使用GPS后记得及时关闭,减少更新频率,根据实际情况切换GPS和网络,不要任何时候都同时使用两者。
---对定位要求不高的业务场景,尽量用网络定位代替GPS.
---慎用持续定位,对于大多数场景,使用一次定位接口即可。
---慎用被动定位,防止被动定位唤醒。
6.4 电池状态
---在处理一个耗时耗电的任务时,如果该任务不是很紧急(例如下载我们应用的更新包),建议事先判断一下电池电量是否足够,如果当前电池电量紧张,可以延迟到一定时间再执行该任务。
---监听充电状态变化(监听设备连接或断开电源状态)来处理特定的业务,以提升用户体验,例如应用更新包策略,以及Log日志上传、用户数据同步等。
6.5 消息广播。程序中避免频繁地监听系统广播或业务消息造成严重耗电问题,灵活控制消息广播接受的有效与无效状态。
6.6 H5页面。关注并测试H5页面的耗电量。
6.7 Android专栏
6.7.1 慎用WakeLock
---使用WakeLock时一定记得成双成对,及时释放。特别是PARTIAL_WAKE_LOCK(PowerManager.new WakeLock()的第一个参数)类型,一定要及时释放。忘记释放或者延迟释放都会导致CPU保持运行,而使得设备处于高功耗状态。
---使用WakeLock时,建议通过代参数的aquire设置超时,以防止APP异常等不可抗拒因素导致没有释放。
---建议通过try-catch-finally的方式确保wakelock被及时释放
try{
wakeLock.setReferenceCounted(false);
wakeLock.acquire(60*1000);
}catch(SomeException e){
//do Exception
}finally{
if(wakeLock.isHeld()){
wakeLock.release();
}
}
---不建议使用的场景。如播放器播放时需要保持屏幕常亮,可以使用WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON或者android:keepScreenOn="true"来代替Wakelock;再如后台服务端数据请求,没必要通过WakeLock来保持屏幕让用户感知等。
6.7.2 定时任务选择。
Android中可以通过Handler/AlarmManager以及JobSchedule(Android5.0+) 3种方式执行定时任务,前台任务建议使用Handler/Timer,简单直观;后台任务,对调度时机没有强烈要求等场景,建议使用JobSchedule来管理任务(Android 5.0+),对于触发事件准确性要求非常高的场景,如果没法通过算法降级处理,再考虑AlarmManager,对于WAKEUP类型且Exact调度模式的AlarmManager任务一定要慎用。
6.7.3 Doze和App Standby。Doze和App Standby是Android 6.0中提供的两个用来节省电量的技术。
---Doze俗称瞌睡,当设备闲置了一段较长时间,Doze技术将通过延迟后台网络活动、CPU运行等来减少电量损耗。
---App Standby,应用待机,可以识别当前App最近是否得到过用户使用,如果没有被使用,APP Standby将延缓这个应用等后台网络活动。
6.7.4 Google官方优化电池寿命建议。
---监控电池电量和充电状态。根据相应的状态来调整应用的更新频率,比如在充电中就可以无虑更新应用对电池的消耗,而如果设备在消耗电池电量,则降低更新频率。
---判断并监测设备的底座状态和类型。通过判断和监听当前底座类型及种类来改变应用程序行为。
---确定和监控网络连接状态。如果设备没有连接互联网,则没有必要唤醒设备类进行更新操作,连接移动互联网比连接Wi-Fi使用更低的更新频率等。
---按需操作BroadcastReceiver。可以在运行时切换自己在Mainfest中声明的BroadcastReceiver,以便根据当前设备状态禁用不需要开启的BroadcastReceiver,从而节省耗电,提高应用效率。
App架构师实践指南四之性能优化一的更多相关文章
- App架构师实践指南六之性能优化三
App架构师实践指南六之性能优化三 2018年08月02日 13:57:57 nicolelili1 阅读数:190 内存性能优化1.内存机制和原理 1.1 内存管理内存时一个基础又高深的话题,从 ...
- App架构师实践指南五之性能优化二
App架构师实践指南五之性能优化二 2018年07月30日 13:08:44 nicolelili1 阅读数:214 从UI和CPU方面来说App流畅体验优化,核心为流畅度/卡顿性能优化. 1.基 ...
- App架构师实践指南二之App开发工具
App架构师实践指南二之App开发工具 1.Android Studio 2.编译调试---条件断点.右键单击断点,在弹出的窗口中输入Condition条件.---日志断点.右键单击断点,在弹 ...
- App架构师实践指南三之基础组件
App架构师实践指南三之基础组件 1.基础组件库随着时间的增长,代码量的逐渐积累,新旧项目之间有太多可以服用的代码.下面是整理的公共代码库. 2.关于加密密钥的保护以及网络传输安全是移动应用安全最关键 ...
- App架构师实践指南一之App基础语法
第二章:App基础语法1.编程范式编程范型或编程范式(programming paradigm),是指从事软件工程的一类典型的编程风格.常见的编程范式有过程化(命令行)编程.事件驱动编程.面向对象编程 ...
- 菜鸟要做架构师(二)——java性能优化之for循环
完成同样的功能,用不同的代码来实现,性能上可能会有比较大的差别,所以对于一些性能敏感的模块来说,对代码进行一定的优化还是很有必要的.今天就来说一下java代码优化的事情,今天主要聊一下对于for(wh ...
- 网易新闻App架构重构实践:DDD正走向流行
网易新闻App架构重构实践:DDD正走向流行 https://mp.weixin.qq.com/s/FdwrT_xn3CQqpWoRVBttvQ 小智 InfoQ 2020-05-14 作者 | 小智 ...
- 【架构师之路】APP架构师必看:面对爆发流量如何进行架构调整
一.APP架构与WEB架构的最大不同 移动APP的架构和传统PC的WEB架构有三点不同: 1.连接的稳定性.在传统的web端连接成功后就可以认为它是稳定的,但在移动端.无线端,APP连接非常敏感,可能 ...
- 通向架构师的道路之 Tomcat 性能调优
一.总结前一天的学习 从"第三天"的性能测试一节中,我们得知了决定性能测试的几个重要指标,它们是: 吞吐量 Responsetime Cpuload MemoryUsage 我们也 ...
随机推荐
- sqlserver服务启动后停止,传递给数据库 'master' 中的日志扫描操作的日志扫描号无效
电脑异常重启,导致SqlServer服务启动后,自动停止,在[计算机管理]-[事件查看器]-[windows日志]中进行查看系统错误日志,在[应用程序]下发现可能的错误信息有以下两条: 1.错误:传递 ...
- Java编码与乱码问题
一.为什么要编码? 由于人类的语言太多,因而表示这些语言的符号太多,无法用计算机的一个基本的存储单元----byte来表示,因而必须要经过拆分或一些翻译工作,才能让计算机能理解. byte一个字节即8 ...
- bootstrap之排版样式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 搬家通知博文地址(将博客搬到CSDN)
(为了确认是您本人在申请搬家,请在原博客发表一 篇标题为<将博客搬至CSDN>的文章,并将文章地址填写在上方的"搬家通知博文地址"中.)
- 基于jsp+servlet图书管理系统之后台用户信息插入操作
前奏: 刚开始接触博客园写博客,就是写写平时学的基础知识,慢慢发现大神写的博客思路很清晰,知识很丰富,非常又价值,反思自己写的,顿时感觉非常low,有相当长一段时间没有分享自己的知识.于是静下心来钻研 ...
- canvas百分百特效
这个特效是别的人,非原创.原创地址 http://blog.csdn.net/lecepin/article/details/53536445 背后的水是可以动的 代码我再研究了下,下面是加了注释的代 ...
- 【BZOJ4919】[Lydsy六月月赛]大根堆
题解: 我觉得数据结构写成结构体还是有必要的 因为不然一道题里出现了两个相同的数据结构由于名字很像很容易出错 另外初始化用segmenttree(){ } 首先裸的dp很好想 f[i][j]表示在i点 ...
- 乐观锁和悲观锁及CAS实现
乐观锁与悲观锁 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁.传统的关系型数据库里边就用到了很多这种锁机制, ...
- python获取公网ip,本地ip及所在国家城市等相关信息收藏
python获取公网ip的几种方式 from urllib2 import urlopen my_ip = urlopen('http://ip.42.pl/raw').read() ...
- HDU 2222 Keywords Search (AC自动机)(模板题)
<题目链接> 题目大意: 给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词. 解题分析: 这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非 ...