性能测试工具 如何快速定位 Android 启动测试中的耗时方法

李雷雷 · 2017年07月04日 · 最后由 Bruce 回复于 2022年08月27日 · 2432 次阅读

机智的防爬虫标识
文章发于知乎专栏 - 测试未来 ,欢迎关注:https://zhuanlan.zhihu.com/c_109570626

工具已开源,地址:https://github.com/alexknight/TraceAnalysis ,欢迎 star

1.启动时间测试常用方案介绍

如何精确测试启动时间,其实这个问题可大可小,主要需要看团队对启动时间的测试精度要求,当启动时间测试误差需要精确到小几十毫秒时,很多问题都会暴露,因为其实目前很难有一种方式去评估数据的有效性。当前设备状态,CPU 温度,内存,系统 GC,研发人员的代码以及线程模式等,都有可能导致启动时间波动增大。目前常用的启动时间测试方案有几种,可以例举一下:

  • 插桩法:通过在整个启动的生命周期打日志,然后通过解析日志来得到本次启动时间
  • 录屏分帧:包括高速摄像头或者其他客户端录屏/截图,通过录制启动时间的整个过程,通过做分帧处理,来得到起始结束位置

但其实这些方法都有各自的问题,插桩引入的测试误差本身很小,但因为系统误差的关系,会导致本身波动会很大,而录屏分帧,虽然可以用于竞品分析,但测试误差会比较大,目前工业级的摄像头,也只能到 8ms/帧率,一般高速摄像头的也会引入 33ms 的系统误差,此外,如果在 android 端录屏,可能会导致启动时间波动更加增大,因此如果单纯从测试方法上来改善启动时间测试,效果肯定不会好。因为我们需要明白,系统随机误差的引入,所以启动时间的测试数据是一个概率问题,而不是一个可以 100% 一定出现在某个区域的问题(有时间写一篇统计学跟误差分析的文章)。
其实自然而然这就引申出两个问题:

  • 问题定位方法的改进
  • 误差需要用科学的方法去做估算

当然这篇文章只讲第一个问题,也就是怎么去定位启动时间问题,下面进入正题。

2.启动时间问题定位方案

在这里要推荐的是TraceviewTraceview的介绍可以看这篇文章:https://testerhome.com/topics/5049

因为系统随机误差比较大,因此单独看某一个生命周期中的耗时,并不能帮助定位问题,而 Traceview 可以帮我们查看到每一个线程的调用栈以及方法的CPU时间或者堆栈累加时间。往往可以通过Traceview来做问题定位,但目前有一些限制:

  • 操作不超过 5s
  • 在 IDE 上查看才比较方便
  • 大部分方法都混淆了,很难有效定位到对应的方法

其实这些问题都不是问题

  • Traceview可以通过android.os.Debug.startMethodTracing();android.os.Debug.stopMethodTracing();来打点,生成这段启动周期的Trace数据
  • google提供了一个半成品dmtracedump,可以解析Traceview文件,当然也只是半成品,但我们可以自己解析,但是是有办法突破IDE限制的
  • 混淆问题其实不算问题,一般都有自己的mapping文件去解混淆

3.方案应用

我们在版本迭代中,每一个小版本演进时,其实变动的方法并不会太多,那么,Traceview既然能看到进程,方法占用的CPU时间片,那我可以把所有的方法耗时做统计并做耗时排序,过滤掉系统线程以及不需要关注的线程,着重对比新增的方法以及改动的方法,然后我们逐一去过滤top异常的方法就行了。

实际应用上可以发现,用反混淆后的包去做对比测试,是可以很明显看到一些异常的耗时方法的。

4.拓展

这块其实还可以继续拓展一下,但我这块没有实践,可以把我的想法抛出来给大家。

  • 反混淆操作
  • 通过对比两个版本的Traceview方法,可以过滤出top方法
  • 拿到两个revision间的svnlog,过滤出改动的方法
  • 对比svnlogtop异常方法,自动将可疑方法邮件发给研发,实现监控问题到定位问题的闭环。

5.工具

  • 该工具可以把对应trace的方法耗时/调用堆栈以及线程关系给解析出来
  • 主要用于在两次版本迭代时,为了迅速找到新版本新增的方法以及异常的方法耗时,可以使用默认的方法来生成报表

另外展示下结果输出

(1). 通过TraceUtils(...).anti_mapping.analysis.get("dict")可以获取解析结果,结果是一个dict/json,格式为

{
    "inclusive": "xx",
    "exclusive": "xx",
    "method_thread": "xx",
    "theads_pid": "xx",
    "call_times": "xx",
    "costs": "xx",
    "sorted_dic": "xx"
}
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 9 条回复 时间 点赞

能有个 demo 就好了

bauul 回复

主要还是懒,因为一整套流程一步步说下来挺麻烦的。不过真的考虑用这种方式做的话,其实都很好理解。说到底,这个工具其实就是提供了一个traceview的反混淆工具以及traceviewparser。另外我补充一下以下两点:

  • 为什么要用这种方法:主要是看中traceviewinclusive/exclusive cpu time可以拿到线程跟方法的cpu时间,以及调用次数,这样可以避免上下文切换,阻塞,GC 等因素干扰,真正的目的也是为了使用自动化的方法分析耗时的方法
  • 关于 demo:其实demo有给出,文章最下面那个报表就是配置完成后,sheet_analysis.py 运行的结果,考虑到通用性问题,其实已经给出了解混淆手段以及 traceview 的解析堆栈,剩下的自己去拓展利用会比较好。

录屏分帧,有这方面的资料吗?

iOS 呢 (抖机灵)?

1717p 回复

没做过 IOS 这块。。。

随便都能找得到把

李雷雷 回复

。。。soga

李雷雷 回复

恩,adb 自带……

你好楼主大大,这种比较偏向于只是应用启动,但是像应用的一些操作怎么去测时间呀,比如说调起输入键盘的时间、下拉通知栏的时间、播放本地视频出现视频第一帧画面的时间,这些比较偏主观的测试点,要怎么自动化去实现呀,我们现有的是通过 ffmpeg 去对录制的视频切帧搭配秒表去做的,但是这种对相机的性能要求也高而且测试时间长,UI 自动化的话还考虑控件查找操作和定位操作的耗时,就算 freeze 页面存下元素来也比较麻烦,然后也有看到有用图像识别库的,那种,有什么好的建议嘛,应该怎么去做好一些。

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