2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Android 性能优化梳理

Android 性能优化梳理

时间:2023-08-17 14:05:28

相关推荐

Android 性能优化梳理

目录

目录

1、内存泄露优化

1.1 抓取内存泄露方法

2、启动优化

2.1、冷启动

2.1.1 抓取冷启动方法

2.2、热启动

2.2.1 抓取热启动方法

2.3 启动优化

3、卡顿优化

3.1、CPU占用查询

3.1.1 通过脚本命令抓取CPU占用

3.1.2抓取trace文件

3.1.3 CPU分析

3.1.4 通过perfetto工具或者systrace分析trace文件

3.2、内存占用分析

3.2.1 通过脚本命令获取内存

3.2.2 抓取trace文件

3.2.3 内存分析

3.3 卡顿分析

4、性能抓取命令总结

5、抓取CPU和内存脚本命令

1、内存泄露优化

1.1 抓取内存泄露方法

方法一(适用于右发际线高着使用):

1、执行dumpsys meminfo ‘包名’记录当前内存占用

2、执行压测脚本循环遍历业务功能

3、压测一段时间后退出界面等待一段时间后输入命令:dumpsys meminfo ‘包名’查看Activities是否为0,内存有无明显增加的情况

方法二(适用于左发际线高着使用):

通过Android Profile抓取内存快照查看是否有内存泄露

1、使用Memory Profile实时跟踪应用的内存信息,针对内存分配异常的情况,可以通过抓取内存快照进行分析

2、点击Profile的Memory显示条即可进入Memory Profile

2、启动优化

2.1、冷启动

2.1.1 抓取冷启动方法

方法一:通过串口命令获取

在测试前先查询进程是否存在 命令 ps -A | grep 包名如果进程存在则需要杀死进程使用 命令 kill -9 进程号在杀死进程后在使用启动命令查看启动时间 命令am start -W 包名/类路径名

应用自身启动耗时,参考TotalTime;

系统启动应用耗时(包含上一个应用activity的pause),参考WaitTime;

方法二:抓取trace判断启动时长

分析冷启动时间:定位到当前应用的UI Thread,如下图,从ZygoteInit到serviceStart后的第一帧结束,查看时间长度做为启动时长(注意该时长比应用测试部用视频采集卡采集的时间要短,视频采集卡采集的是用户感知的真正时长,我们这里的时长仅用作自己应用启动时长分析);

2.2、热启动

2.2.1 抓取热启动方法

方法一:通过命令抓取

让应用退出前台在测试前先查询进程是否存在,如果存在在进行下步操作 命令 ps -A | grep 包名使用启动命令查看启动时间 命令am start -W 包名/类路径名

方法二:抓取trace判断启动时长

分析热启动时间:定位到当前应用的UI Thread,如果是activity进入,则从activityStart到serviceStart后的第一帧结束,查看时间长度做为启动时长。

如果是service进入,则从serviceCreate到serviceStart后的第一帧结束,查看时间长度做为启动时长。

2.3 启动优化

启动我们可以查看是否Application初始化或者Activity初始化时存在耗时,可以做出如下改善

ContentProvider:

ContentProvider的onCreate方法会在Application的onCreate方法前执行,其onCreate方法不要放耗时操作,可以通过Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler()延时加载

Application层面:

将Application的onCreate方法中第三方SDK初始化放入线程中处理Multidex预加载优化,5.0以下多dex情况

Activity层面:

首屏Activity的渲染不要有耗时操作,如果有可以放入子线程或者IntentService中处理预创建Activity,对象预创建预加载数据

UI层面:

消除启动时的白屏、黑屏。windowbackground避免布局嵌套,多层嵌套

参考:启动优化

3、卡顿优化

3.1、CPU占用查询

3.1.1 通过脚本命令抓取CPU占用

1、定义脚本文件gen_memory.sh(代码在第五章节),修改包名和U盘挂载路径

2、将gen_memory.sh拷贝到/data/目录,赋权限777(chmod 777)

3、运行脚本(进入到data目录后输入 ./gen_memory.sh),然后遍历各选项功能;

4、退出应用,然后运行脚本(进入到data目录后输入 ./gen_memory.sh);

5、等待一段时间后,建议10分钟以上,拔出U盘,查看U盘中指定包名文件夹下的cpu.csv文件,进行分析查看内存占用是否合理。

3.1.2抓取trace文件

1、通过脚本命令抓取trace

抓取10秒内trace:

atrace -z -b 10000 gfx input view wm am res dalvik rs sched freq idle disk binder_driver binder_lock -t 10 > /data/trace_output1.atrace

持续抓取:

开始抓取 atrace --async_start -c -b 12800 -z gfx view input webview wm am sm audio video camera hal dalvik res rs bionic pm ss database network disk sched freq idle binder_lock binder_driver

复现到后停止 atrace --async_stop -c -b 12800 -z -o /data/local/tmp/trace.out

2、通过profile抓取trace

3.1.3 CPU分析

CPU Profile可以跟踪如下几种数据:

Sample Java Method 为间断采样,适用于大部分情况,profile调试不会对现有程序造成影响Trace Java Method 持续采集,适用于跟踪全部method执行状况,会对现有程序运行造成影响Sample C 跟踪C层函数(Android 8.0+)Trace System Call 跟踪系统调用,如核心运行状态和掉帧情况(Android 7.0+)

3.1.4 通过perfetto工具或者systrace分析trace文件

systrace是google 提供的一个分析工具,脚本命令为Android SDK的platform-tools\systrace\systrace.py , 它的运行依赖python2.7+,所以在进行trace分析前需要安装python对应环境。

转换命令:python "D:\Program Files\Android\sdk\platform-tools\systrace\systrace.py" --from-file=D:\9615_trace\trace008.out

我们可以从frame看出是那一帧卡顿,红色是验证卡顿、橙色为轻微卡顿、绿色不卡顿。然后再从堆栈分析draw、layout的耗时情况。

线程状态

绿色:正在运行,线程正在完成与某个进程相关的工作或正在响应中断。

蓝色:可运行,线程可以运行但目前未进行调度。

白色:休眠,线程没有可执行的任务,可能是因为线程在遇到斥锁定时被阻止。

橙色:不可中断的休眠,线程在遇到 I/O 操作时被阻止或正在等待磁盘操作完成。

紫色:可中断的休眠,线程在遇到另一项内核操作(通常是内存管理)时被阻止。

3.2、内存占用分析

3.2.1 通过脚本命令获取内存

1、定义脚本文件gen_cpu.sh(代码在第五章节),修改包名和U盘挂载路径

2、将gen_cpu.sh拷贝到/data/目录,赋权限777

3、运行脚本(进入到data目录后输入 ./gen_cpu.sh),然后遍历各选项功能;

4、退出应用,然后运行脚本(进入到data目录后输入 ./gen_cpu.sh);

5、等待一段时间后,建议10分钟以上,拔出U盘,查看U盘中指定包名文件夹下的meminfo.csv文件,进行分析查看内存占用是否合理。

3.2.2 抓取trace文件

1、通过脚本命令抓取trace

抓取10秒内trace:

atrace -z -b 10000 gfx input view wm am res dalvik rs sched freq idle disk binder_driver binder_lock -t 10 > /data/trace_output1.atrace

持续抓取:

开始抓取 atrace --async_start -c -b 12800 -z gfx view input webview wm am sm audio video camera hal dalvik res rs bionic pm ss database network disk sched freq idle binder_lock binder_driver

复现到后停止 atrace --async_stop -c -b 12800 -z -o /data/local/tmp/trace.out

2、通过profile抓取trace

3.2.3 内存分析

内存分类:

Java表示Java代码或Kotlin代码分配的内存;Native表示C或C++代码分配的内存(即使App没有native层,调用framework代码时,也有可能触发分配native内存);Graphics表示图像相关缓存队列占用的内存;Stack表示native和java占用的栈内存;Code表示代码、资源文件、库文件等占用的内存;Others表示无法明确分类的内存;

3.3 卡顿分析

Systrace会统计卡顿的具体类型,一般常用的类型有:

Scheduling delay:调度延迟Expensive measure/layout pass:绘测或者布局时间长Long View#draw: view 绘制时间长

导致卡顿可能有如下原因:

过于复杂的布局UI线程的复杂运算频繁的GC,如内存抖动,即大量的对象被创建后又短时间被回收,或者瞬间产生大量的对象会严重占用内存区域

4、性能抓取命令总结

5、抓取CPU和内存脚本命令

#!/system/bin/sh#设置包名packagename="";#设置U盘路径path="/mnt/media_rw/2DD0-A606/$packagename";#设置du与dumpsys的间隔时间sleeptime=15#设置top间隔时间,建议15秒以上toptime=15a=0b=0c=0d=0#设置总次数total=100000#设置常量u=1024#v=6if [ ! -d "$path" ]; then mkdir $pathelse rm -rf $pathmkdir $pathfi ;#查看Android版本v=$(getprop|grep ro.build.version.release |awk '{print$2}'|awk '{print substr($1,2,1)}');echo $v >> $path/android_ver.csv ;#获取CPU个数processor=$(($(cat /sys/devices/system/cpu/possible |awk -F'[-]' '{print$2}')+1));#生成ddr表的表头echo -n "time," >> $path/meminfo.csv;echo -n "meminfo," >> $path/meminfo.csv;echo "Activity" >> $path/meminfo.csv;#生成cpu表的表头echo -n "time," >> $path/cpu.csv;echo -n "cpu," >> $path/cpu.csv;echo "Activity" >> $path/cpu.csv;while (($b < $total));do let "b += 1";if [ -d "$path" ]; then echo -n $(date "+%H:%M:%S,") >>$path/meminfo.csv;#echo -n $(date "+%H:%M:%S,") >>$path/ddr.csv;#输出Meminfo大小 单位:Mddr=$(dumpsys meminfo $packagename |grep TOTAL |awk 'BEGIN{ddr=0}{ddr += $2}END{print ddr}');echo -n "`awk -v ddr=$ddr -v u=$u 'BEGIN{printf "%.2f",ddr/u}'`," >>$path/meminfo.csv;#获取当前Activityecho $(dumpsys window |grep mCurrentFocus |awk '{print$3}'|awk -F "}" '{print$1}') >>$path/meminfo.csv;sleep $sleeptime;fi ;done&while (($c < $total));do let "c += 1";if [ -d "$path" ];then #CPUcpu=$(top -b -n 1|grep $packagename|awk 'BEGIN{cpu=0}{cpu += $9} END {print cpu"%"}');echo -n $(date "+%H:%M:%S,") >>$path/cpu.csv;#生成CPU占用echo -n "`awk -v cpu=$cpu -v processor=$processor 'BEGIN{printf "%.2f%%",cpu/processor}'`," >>$path/cpu.csv;#获取当前Activityecho "`dumpsys window |grep mCurrentFocus |awk '{print$3}'|awk -F "}" '{print$1}'`," >>$path/cpu.csv;sleep $toptime;fi ;done&

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。