移动性能测试 阿里巴巴 Android 性能测试工具 mobileperf 开源 (天猫精灵 Android 性能测试 - 线下篇)

look · 2020年05月06日 · 最后由 阳光it宅男 回复于 2022年12月06日 · 16147 次阅读

官方首发 阿里巴巴技术质量:Android 性能测试工具 mobileperf 开源 (天猫精灵 Android 性能测试 - 线下篇)

背景

Android 性能稳定性测试工具mobileperf github 如果您觉得有帮助,请给个 star,有问题欢迎加入文底钉钉群交流

露客 2018 年加入天猫精灵,之前有过一些性能 稳定性测试经验,但天猫精灵跟我之前的项目经验不太一样,之前大多服务于单独的 APP,比如测手淘就只是测手淘,而天猫精灵业务更复杂一些,主要有如下挑战:

1、除了天猫精灵手机 APP,还有带屏天猫精灵上很多 APP 都需要支持,比如天猫精灵 CC 上有 13 个 app,每个 app 使用场景各有不同,涵盖了通讯录、视频、音乐、购物等各种场景

2、相比手机 app,除了点击操作的触屏链路,天猫精灵还有语音链路

3、手机 app monkey test 一般可能也就云测平台上跑几个小时,语音压测需要连续测试 72 个小时以上,测试时长远超云测工具,对工具的稳定性提出了新的要求

4、相对现在定价动辄几千块,均价 2 千左右的手机,天猫精灵定价只有几百,硬件配置差些,所遇到的性能 稳定性挑战会更严峻

需求

本着前期先能发现问题,再深入定位问题,所以确定了线下、线上分步走的策略

1、线下方案,能方便采集性能数据,工具要支持 Android 手机、天猫精灵各种 Android 定制设备,支持 Android 全版本,轻量化,使用低门槛,尽可能少侵入甚至零侵入设备

2、线上性能指标 问题定位

本文是 Android 线下篇

线下方案选型

工具选型

  • Android App

​ 代表:开源工具腾讯 GT网易 Emmagee

​ 劣势:Android 低版本有些功能需要 root,Android 高版本跨进程获取数据,权限限制,不兼容

  • PC adb 工具

​ 优势:非侵入,权限高,能发现问题

​ 劣势:需要连接数据线,便携性差点

  • SDK

劣势:侵入式,需集成 SDK,不利于做竞品测试

GT github 上已表示 Android GT 后续不再支持 GT APP 版本,只支持 GT SDK

由于 Android 权限控制越来越严格,通过 APP 跨进程获取性能数据在 Android 高版本已越来越困难,由于 adb shell 权限比较高,相信 Android 会一直开放开发者权限,故方案选型阶段,采用了依赖 adb 的方案,开发了一套 Android 性能数据采集工具 mobileperf

还有一种思路,仍然是 app 形态,但用了 adb wifi 通道,露客之前也有过一些测试工具 app 的经验,相比采用 adb usb 方式 mobileperf 的担忧:

  • 测试工具 app,应用进程优先级,还是会受 Android 限制,担心系统资源不足,测试进程优先级不高,被系统 kill 概率大,在 IOT 低端设备上被 kill 概率更大,进程保活是业界难题,黑科技手段层出不穷,并且存在随时被官方封杀的风险,路只会越走越窄,mobileperf 是 PC 程序,除非 adb usb 方式不能用了,设备失联,关机等恶劣情况,都 OK,与其花费很大精力探索各种黑科技上,还不如把精力放在 Android 允许范围内倒腾
  • 带屏天猫精灵都是定制 Android 系统,测试工具 app 可能要做单独的适配,兼容性成本高点,这点 mobileperf 不用担心,只要是 Android 系统、adb 能用就可以,在各种 Android 定制设备,使用成本更低
  • 由于是 APP,系统需要单独分配资源,比如工具发现的 anr,开发童鞋一看 cpu 占用信息,如果发现测试工具 app 占用 cpu 较高,就很容易受到挑战,找工具的锅(不排除有些 ANR 确实是工具导致的),而 mobileperf 采集都依赖系统命令,这种影响小些

  • 长时间测试,比如 72 小时以上,adb wifi 担心会有点不稳定,毕竟要依赖网络

工具对比

mobileperf 跟 GT APP 对比如下:
工具对比

架构

mobileperf 整体架构图:

架构图

工具自身影响

mobileperf 对 PC 的影响

对PC的影响

测试 PC:MacBook Pro (Retina,15-inch, Mid 2015) 2.2 GHz 四核 Intel Core i7

工具稳定性:mobileperf 能支持跑 72 个小时以上,adb 断开重连都能继续采集

工具适用性:支持 mac linux windows 平台

工具 Android 兼容性验证

mobileperf Android 版本兼容性验证结果如下

phone model Android version result
HUAWEI Mate20 HMA-AL00 10 pass
HUAWEI Mate10 ALP-TL00 10 pass
Xiaomi MI 8 10 pass
HUAWEI Mate20 HMA-AL00 9 pass
HUAWEI Mate10 ALP-TL00 9 pass
HUAWEI Mate9 MHA-AL00 9 pass
HUAWEI P10 Plus 9 pass
HUAWEI Honor AL10 9 pass
samsung Note9 SM-N9600 8.1.0 pass
Oppo R15 PACM00 8.1.0 pass
VIVO X23 8.1.0 pass
XiaoMi Note3 8.1.0 pass
RedMi note5 8.1.0 pass
Xiaomi MI 5 8.0.0 pass
smartisan OD103 7.1.1 pass
HUAWEI TRT-AL00 7.0 pass
vivo Y66 6.0.1 pass
XiaoMi Mi2 5.0.2 pass

#

效果

mobileperf 在项目中使用 1 年半,天猫精灵总共发现了性能 稳定性类问题几百个,bug 解决率都是 100%

采集原理

cpu

方案调研

1、dumpsys cpuinfo

2、top 命令

3、通过 proc/stat 计算 cpu 使用率

两者区别:Android CPU 使用率:top 和 dump cpuinfo 的不同,看网上一番讨论,top 更准

通过实验发现采集频率非常快时,top 有点耗 cpu,对手机本身性能有影响,自测,采集频率 1s,top 在低端手机上(红米)会占到 7%(100% 统计方式)的 cpu 使用率,天猫精灵采集频率 5s,会有 20% 占用(400% 统计方式),发现 top 的底层实现是读取 proc 文件,top 对每个进程都有计算

网上提供了一种计算方式,原理上跟 top 一样,如果计算指定进程的 cpu 使用率,只需读对应的 proc 文件,通过 jiffies 计算就可以了,这样比 top 方式占用 cpu 低,计算方式如下

整机 cpu 使用率

通过读取/proc/stat ,这个文件包含了所有 cpu 核的汇总情况,所以后面计算不用考虑核数,占用率不会超过 100%

cpu 使用时间 = user+nice+system+iowait+irq+softirq

CPU 总时间=user+nice+system+idle+iowait+irq+softirq = cpu 使用时间 +cpu idle 时间

总 cpu 使用率=(cpu 使用时间 2-cpu 使用时间 1)/(cpu 总时间 2-cpu 总时间 1)*100%

进程 cpu 使用率

通过读取/proc/pid/stat

进程 cpu 使用时间 = utime+stime

进程 cpu 使用率=(进程 cpu 使用时间 2-进程 cpu 使用时间 1)/(cpu 总时间 2-cpu 总时间 1)*100%

选定方案

采集时间间隔 ,配置文件中默认 5 秒,由于对采集频率要求不高,top 支持同时采集多进程,结果简单易处理,实时性 可信度高,决定采用 top 的方式

测试过程中会生成 cpuinfo.csv,可以测试过程中查看,表中各列解释

cpu table

汇总 xlsx 文件会在测试结束后生成,xlsx 数据跟 csv 数据完全一致,xlsx 汇总是根据 csv 的数据画的曲线(csv 没有画图功能)

cpu trend

内存

整机内存 可用内存通过 dumpsys meminfo 获取 Total RAM 、Free RAM

各进程 pss 通过 dumpsys meminfo package 获取 TOTAL 行 Pss Total 所在列的值,各进程 PSS 也可以通过 dumpsys meminfo 获取,只是拿不到各进程更详细的内存占比情况,比如堆大小、native、system、so 大小等

经在 CC 上测试发现 dumpsys meminfo 比 dumpsy meminfo package 耗时长,dumpsys meminfo 耗时 6s 多,dumpsys meminfo package 能在一秒内完成,采集频率 5s,dumpsy meminfo 会导致 CC 上 system_server 系统进程 cpu 由 2% 增高到 80%,所以降低了 dumpsys meminfo 采集频率,采用 10 倍设置频率采集(比如 dumpsys meminfo package 5s,dumpsy meminfo 则 50s)

由于要支持多进程的情况,现在各进程 pss 通过解析 dumpsys meminfo 结果得到,dumpsys meminfo package 来获取各个进程的详细内存情况

在测试过程中会生成一个 meminfo.csv 文件,可以查看,表中各列解释
mem table

这个 csv 表格是用 dumpsys meminfo 得出的,汇总 xlsx 文件会在测试结束后生成,对应 meminfo 这个表格
mem trend

每个进程会有 pss_部分包名的 csv 表格,这个表格是用 dumpsys meminfo package 得出的

pss table

能把每个进程的详细内存展示出来

汇总 xlsx 中对应 pss_部分包名这个表格

pss trend

如果进程发生了内存泄露,根据曲线,很方便一眼就看出是哪部分导致泄漏

为了帮助定位内存泄漏问题,工具每隔一个小时会执行 am dumpheap package ,dump 进程内存,但不能像 LeakCanary 直接翻译出 GC 引用链,仍需人工分析下

流畅度(fps/丢帧)

fps 通过 dumpsys SurfaceFlinger 或 dumpsys gfxinfo(android8.0 之后) 获得最近 128 帧数据计算得出,fps=帧数/耗费时间

如果以上两种方式都不 OK,机器有 root,用 service call SurfaceFlinger 1013 获取帧数

通过 dumpsys SurfaceFlinger 的方式还会计算丢帧 janky 值

丢帧:相邻两次绘制之间的丢帧数,丢帧数越多,说明问题越严重,mobileperf 默认丢帧数超过 10 帧算是严重丢帧

流畅度数据在 fps.csv 中

表中各列解释

fps table

页面打开耗时

mobileperf 从 logcat 日志中抓取 am_activity_fully_drawn_time 和 am_activity_launch_time(大多数情况)日志,

会生成 launch_logcat.csv

launcher table

不过这种方式有个弊端,日志的耗时不能完全反馈真实的体验耗时,我们内部已有其他方案测试启动耗时

monkey(可限制 activity)

mobileperf 调用了 Android 原生的 monkey,如果您想限制在指定内 activity 内跑 monkey ,可以通过配置项,开启 monkey 后,会在测试目录下生成 monkey.log

#如果需要在限定activity内做monkey test,main_activity是模块的几个主入口,用分号; 分隔
#main_activity=com.alibaba.ailabs.genie.contacts.MainActivity
#activity_list是准许的activity,main_activity开启前提下有效
activity_list=com.alibaba.ailabs.genie.contacts.MainActivity;
        com.alibaba.ailabs.genie.contacts.cmd.CmdDispatchActivity;
        com.alibaba.ailabs.genie.contacts.cmd.transform.VoipToPstnActivity;
        com.alibaba.ailabs.genie.contacts.add.AddContactsActivity;
        com.alibaba.ailabs.genie.contacts.avatar.TakePhotoActivity;
        com.alibaba.ailabs.genie.contacts.details.DetailsActivity;
        com.alibaba.ailabs.genie.contacts.add.RelationshipActivity;
        com.alibaba.ailabs.genie.contacts.details.DownloadTipsActivity;
        com.alibaba.ailabs.genie.contacts.details.DownloadTipsMiniActivity;
        com.alibaba.ailabs.genie.contacts.cmd.selectlist.call.VCallListActivity;
        com.alibaba.ailabs.genie.contacts.cmd.selectlist.contacts.VContactListActivity;
        com.alibaba.ailabs.genie.contacts.message.VoiceDetailsActivity

logcat 日志(支持异常日志检测)

工具会保留全量 logcat 日志,每隔 60 万行会新建文件,辅助定位问题

logcat file

如果配置文件中配置了异常日志

exception config

会将 logcat 中出现的异常日志都保存在 exception.log 中

exception log

根据异常汇总日志,再去 logcat 日志查看详细上下文信息,可以快速定位问题

流量

通过读取/proc/net/xt_qtaguid/stats 文件获取,因为 Android 提供的流量统计 API – TrafficStats 中,对 uid 进行流量统计的方法,能区分应用,底层就是读取了该文件

Android 性能测试之网络流量

流量数据在 traffics_uid.csv 中,表中各列解释

traffic table

<=android9 读取/proc/net/xt_qtaguid/stats 获取流量

Android10,/proc/net/xt_qtaguid/stats not found,用/proc/net/dev /proc/pid/net/dev 获取流量

电量

先通过 dumpsys batteryproperties 获取,如果获取不到,再通过 dumpsys battery 获取(Android9)

问题:插着 usb,这两种方式获取到的并不精准,并非专业级电流电量测试,只能作为参考

电量数据在 powerinfo.csv 中,表中各列解释

power table

由于功耗软件测试方式不太精准,我们内部已用硬件方案测试功耗,此项 mobileperf 中默认关闭

常驻进程 pid 监控

天猫精灵是整机,跟很多手机 app 不一样,是应用级别 app,可能会被用户手动 kill 掉,天猫精灵上有些系统优先级进程,不能挂掉,一旦挂掉,会导致无法使用,所以 mobileperf 新增了常驻进程 pid 监控,一旦 pid 发生了变化,认为发生了异常

#常驻进程,需要关注pid变化,多个进程,英文分号分隔
pid_change_focus_package=com.alibaba.ailabs.genie.smartapp;com.alibaba.ailabs.genie.smartapp:core

磁盘剩余空间检查

天猫精灵跟很多手机 app 不一样,随便压测就是 3 天以上,如果有写文件不正常,占满磁盘空间,会导致机器彻底无法使用,影响用户体验,所以测试结束时,添加了对磁盘剩余空间检查,如果使用空间超过 80%,则自动提单

进程线程数

通过进程名获取 pid,ls -lt /proc/pid/task,统计多少行数即线程数

答疑

为了方便大家更容易的接入 mobileperf 或讨论相关技术,大家可加入钉钉交流群 32266824。为了方便大家交流,入群请注明姓名与公司等信息。

dingding qr code

最佳回复

不过这种方式有个弊端,日志的耗时不能完全反馈真实的体验耗时,我们内部已有其他方案测试启动耗时

一直也比较困惑启动时间该如何测试,实际用户体验的启动时间与打点计算出来的有明显差异,可以透露下贵司内部的其它测试方案吗

look 回复

2.如下图 1 与 2,二者的不同的就是第一个群与第二群位置变换,原因是第一张图上为启动过程中加载完所有群,但是需求还有一个逻辑,就是东方时尚那个群符合某个特殊条件,在排序中优先于第二个群,这个特殊条件是从接口获取的,等于是加载完首页群,又获取到一个接口数据,进行再排序,东方时尚就有第二位调整到第一位,整个过程给人的体感是,未重新排序之前页面已经很完整了,或许一些用户认为启动已经完成,但是之后确实又有了一个变动,二者位置调换,所以想请教下,像这种加载完之后的基于接口的逻辑再处理要不要计入启动过程


共收到 22 条回复 时间 点赞

源码在 github 上。有几个问题:

  1. 对游戏类 app 的 FPS 采集有问题,我测试的 Unity 游戏的 FPS 采集到的都是 0;
  2. 得到的 cpu info 的百分比占用没有归一化
  3. 内存数据还是用 dumpsys meminfo 的方法采集,这个方法如同它源码所说的一样:有很大的性能问题。所以导致采集频率不能太高。

非常期待阿里爸爸能够给出更好的解决方案。

Mark 一下 Mark 一下

不过这种方式有个弊端,日志的耗时不能完全反馈真实的体验耗时,我们内部已有其他方案测试启动耗时

一直也比较困惑启动时间该如何测试,实际用户体验的启动时间与打点计算出来的有明显差异,可以透露下贵司内部的其它测试方案吗

感谢 LZ 分享,学习下用到自己项目中😂 😂 😂

感谢分享!先试用一下

look #8 · 2020年05月08日 Author
秦岭 回复

录屏分帧,结合图像识别,这样更贴近用户真实体验耗时,在项目受认可

look #9 · 2020年05月08日 Author
chentianqin 回复

fps 需要在滑动时才有值,静止时是 0,前提需排除静止的情况
1、Unity 没有测试过,如果不是用的 Android 那一套绘制,可能获取不到
2、cpu 百分比占用没有归一化是指没有换成 100% 的统计方式?恩,现在是 X 个核,就是 X*100% 的统计方式,自己 fork 下,除以核数,处理下不难
3、dumpsys meminfo 在低端手机上耗时 5 6S,中高端手机 1s 左右,手机配置越来越好,如果官方觉得不是问题,估计不会优化了

10楼 已删除
look 回复

大佬再请教一下,目前录屏分帧这个方法,有些计时标准相关的疑问,以方便分离开,所以分开以几个回复,还请帮忙指导下,谢谢。

1.如下图淘宝,可见这个界面控件已经加载出来,部分内容也加载出来,但是部分图片尚未显示出来,因为淘宝这类产品首页图片非常之多,加载耗时在所难免,如果计时到所有图片都加载出来,得出的启动时间会比较难看,所以想参考下,阿里计时确实是等待所有图片都加载完才叫启动结束吗,还是计时到控件 框架加载完毕,部分图片加载完毕,大致显示 ok 即可?

look 回复

2.如下图 1 与 2,二者的不同的就是第一个群与第二群位置变换,原因是第一张图上为启动过程中加载完所有群,但是需求还有一个逻辑,就是东方时尚那个群符合某个特殊条件,在排序中优先于第二个群,这个特殊条件是从接口获取的,等于是加载完首页群,又获取到一个接口数据,进行再排序,东方时尚就有第二位调整到第一位,整个过程给人的体感是,未重新排序之前页面已经很完整了,或许一些用户认为启动已经完成,但是之后确实又有了一个变动,二者位置调换,所以想请教下,像这种加载完之后的基于接口的逻辑再处理要不要计入启动过程


look 回复

3.如下图,控件与图片,业务内容基本全部加载出来了,但是仍然要刷新,理由是智能推荐每次启动都会更新一批,然而这个更新的数据内容是在第一页的最底部,用户能看到的部分都没变,这种计时到'加载完'三个字消失,还是看到大部分页面内容没有变化,不用等 ‘加载完’ 消失呢,谢谢!!

look #14 · 2020年05月10日 Author
秦岭 回复

这个要看产品形态和你们团队怎么协商了,有的以第一张图片加载完为结束,有的以用户可操作为结束,有的以全部加载完成为结束点

秦岭 回复

哈哈哈,终于看到了一样的问题,团队内部之前坚持的就是肉眼看完全启动完,但是不同的人去测本身就有偏差。
再者说性能本身就是零点几秒的慢慢误差,要是看图说话这么猜太难了。
所以还是要测量,图片对比这个我们暂时没搞。
我试了下 XCTestMetric 的启动时间测试,虽然没有完整覆盖图片下载这部分(其实不算 app 启动过程吧)。图片的异步加载和 app 本身的初始化和启动从技术上看是不是可以分开看,不然网络环境的波动以及图片资源大小的变化本身就使得这个测量过程没说服力了

李鹏 回复

我的方法是尽量使用同一个环境,这样受网络波动影响会小些,测多组数据,舍弃最大最小,剩下的求平均,这样更符合统计学!!

但是现在最麻烦的就是如何确定结束界面在哪个,就像我上面的疑问一样,到底是页面全部加载完,还是可用(其实可用状态只是图片加载了一部分,部分接口请求数据还未完成刷新),因为之前是简单的命令取页面渲染前的值为启动时间,未曾用图片切割,所以一直困在该如何确定结束标准,如果定的过于靠后时间过长又不好说服开发与老板,如果定的太前则有很多主观性(比如说可用这个,看起来有主观的因素,不好度量),加上他们都是老思维,用的打点日志方法,如何让他们接收这种测试结果!!

秦岭 回复

完全体会到你的难处,我也是想办法说服同事和老板来着。
这么说吧。app 的库编译连接啥的这个 app 首页 UI 框架的构造、渲染,以及框架出现后各个图片的加载。到底技术上和业务上如何定义 app 启动过程,真的是个坑。
1.比如你测试的启动时间长了,有没有想过开发如何优化
2.或者你首页 UI 从 10 张轮播图变成 1 张,那么 app 启动性能变化了么?(此处作为探讨)
3.如何对比不同 UI 甚至 UI 更新逻辑的 app 之间的启动性能?比如我们的 app 甚至首页模块都是智能推荐,每次启动由于投放内容和用户行为,出现不同结构的数据流,你拿哪一种 UI 结构当做本 app 的启动性能呢?

目前 XCTestMetric 测量 app 开始创建到 firstFrameRender,想必有它的理由,但是说服领导有点难

恒温 《Android 性能测试初探》合集 中提及了此贴 05月14日 15:34

你好,我想问一下 功耗在哪里可以打开,进行测试?

look #20 · 2021年10月08日 Author
萍尤 回复

startup.py 里搜下 PowerMonitor,把注释去掉

look 回复

找到了 谢谢

这个是不维护了吗? 怎么加不了钉钉群了😹

look #24 · 2022年08月01日 Author
萍尤 回复

有在维护,钉钉二维码可能失效了

大佬现在还有交流群最新的入群方式嘛

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册