移动性能测试 iOS 性能专项初探

testly · June 08, 2015 · Last by testly replied at April 20, 2017 · 4189 hits
本帖已被设为精华帖!

前言

iOS性能测试是什么?

iOS性能测试是指基于iOS平台从:
资源消耗
内存泄露
流量消耗
耗电功率
渲染效果
加载时间
等等.....
这些方面配合一些对应场景去收集数据然后根据数据去分析和定位可能存在的问题!

为什么做这个性能测试?
其实在现在很多企业的功能测试和后台API的测试已经相对较为成熟尤其是功能测试。
但是即使是这样,尽管你的应用有多牛B,你的后台架构有多好,你别忘了你最终还是基于平台来跑,
所以你的应用在平台里面的运行效果不好(Crach率高达百分之几十,内存泄露遍布整个流程)的话,其他的也都是多余的........

做完有什么用?
这个问题我只能说,只要自己用心去一项项去做!研究透!你会发现很多的问题!
比如你设计几个场景然后把这几个场景一个个单独跑一遍,把数据拿出来分析一下,你会发现资源占用较高或者内存泄露严重的步骤一步一步去检查代码会发现确实有问题存在,有可能是垃圾对象冗余,也可能是接口数据太大,json解析消耗较高或者其他等等.....

怎么去做?
Instruments 里面集成的很不错了!所以这里用Instruments 里面的工具来做的!
一项一项来:

1,资源消耗(Cpu、内存):

可以直接用Xcode真机Debug

上图大家都知道怎么看吧,比较简单。也可以用(Activity Monitor)不过没有上面这个方法简单粗暴

2,内存泄露Leaks:

选中内存泄露红色区域后下面的列表会把泄露的所以相关内容在下面列表展示,你可以直接找到比例最高的方法直接定位到代码里面!
实例:

关于:tableView:didSelectRowAtIndexPath ,分析下它的内存过程:
sushiString变量通过autorelease创建,它的引用计数是1.

这行代码使得引用计数增加到2, _lastSushiSelected = [sushiString retain];
这个方法结束时,sushiString的autorelease生效了,这个变量的引用计数减少为1
当再次执行tableView:didSelectRowAtIndexPath这个方法时,_lastSushiSelected被赋值了新指针,老的_lastSushiSelected的引用计数还是1,没有被释放,所以产生了内存泄露。

3,启动耗时

两种方法:一种使用NSLog,另外一种使用Time Profiler。

使用NSLog

    CFAbsoluteTime StartTime;
int main(int argc, char **argv) {
StartTime = CFAbsoluteTimeGetCurrent();
// ...
}
- (void)applicationDidFinishLaunching:(UIApplication *)app {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Launched in %f sec", CFAbsoluteTimeGetCurrent() - StartTime);
});
// ...
}

使用Time Profiler
Instruments->Time Profiler
Profile你的app
切换到CPU strategy view,找到你的app启动的第一帧
搜索-[UIApplication _reportAppLaunchFinished]
找到包含-[UIApplication _reportAppLaunchFinished]的最后一帧,即可计算出启动时间

你也可以粗略看下把有波动的部分选上会有一个时间出来!

3,流量(Network):

4,加载时间(Time Profiler):
当我们发现App有点卡的时候,可以通过Time Profiler来看耗时在哪里。

右边的 call Tree 一定要记得选上!下面是这些选项代表的意义!

Separate By Thread:线程分离,只有这样才能在调用路径中能够清晰看到占用CPU最大的线程.
Invert Call Tree:从上到下跟踪堆栈信息.这个选项可以快捷的看到方法调用路径最深方法占用CPU耗时,比如FuncA{FunB{FunC}},勾选后堆栈以C->B->A把调用层级最深的C显示最外面.
Hide Missing Symbols:如果dSYM无法找到你的APP或者调用系统框架的话,那么表中将看到调用方法名只能看到16进制的数值,勾选这个选项则可以隐藏这些符号,便于简化分析数据.
Hide System Libraries:这个就更有用了,勾选后耗时调用路径只会显示app耗时的代码,性能分析普遍我们都比较关系自己代码的耗时而不是系统的.基本是必选项.注意有些代码耗时也会纳入系统层级,可以进行勾选前后前后对执行路径进行比对会非常有用.

5,电量消耗(EnergyDiagnostics)

这个主要是看那个Cpu Activity吧,我也在待研究状态,我怀疑这个工具并不是很准!

上面这些都是浅浅的跟大家说了一下怎么拿到一些数据!
拿到数据之后把他们收集起来分析一下,你会发现有一些场景或操作的系统资源异常,这个时候你可以抱着怀疑的态度去看看代码,也可以跟开发一起去过一下这场景相关的代码,看看是哪里导致这个消耗较大!数据接口量太大?json解析导致?对象没有释放?....

欢迎一起交流,一起进步 可以关注我的微信公众号:“测试开发进阶” - 点我关注

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 43 条回复 时间 点赞

我问个问题。Network这个只有total的,你怎么过滤应用,或者针对应用场景怎么办

testly #2 · June 08, 2015 作者

#1楼 @monkey NetReport 的total针对场景的话可以用步骤结束发送和接收的total减掉步骤前的total 就是步骤所消耗的total?

#2楼 @testly 额。。其他应用的流量不会算进去?

testly #4 · June 08, 2015 作者

#3楼 @monkey 这是在Xcode Session->build 调试当前应用的 就算其他应用操作请求网络这里都没有计数的!这里的计数只针对当前应用的流量

#4楼 @testly 确认?iOS系统的一些流量会算进去么?比如apple.xxxx.com等呢。另外这个只能精确到0.xkb?

testly #6 · June 08, 2015 作者

#5楼 @monkey 反正我的打开任何一个应用都不会计数,唯有被测应用,你说的apple.xxx.com会不会占用我真不确定!精确的问题可以有策略的!

#6楼 @testly 这个有total么。。。另外remote如果是集群的话,很多ip怎么区分?= =

而且in和out区别开来的。。。然后处以1024?

testly #9 · June 08, 2015 作者

#8楼 @monkey 是这样,不过这个下面的列表是瞬时的,不会一直保存

testly #10 · June 08, 2015 作者

#7楼 @monkey ip是资源请求的地址的ip吧 我暂时没有去区分,对我而言都是流量的出和进

#9楼 @testly 这不是统计起来很麻烦么。。= =。。ip是资源请求的ip地址。但是面对集群的时候,就会有很多服务和ip,到时候统计起来会很麻烦。。。这个有没有好的方式?

testly #12 · June 08, 2015 作者

#11楼 @monkey 麻烦也得做啊!不要求精确的话可以 直接看上面的total,无论是集群都是从这边出进的!用 tcpdump 抓包也很麻烦的!

#12楼 @testly 如果面试别人这样问,你也这样回答别人么。。= =

testly #14 · June 08, 2015 作者

#13楼 @monkey tcpdump+wireshark 可以做到,而且精确!你懂得!

#14楼 @testly 不懂。。。

#14楼 @testly 不懂。。。

#15楼 @monkey 你之前不是说发朋友圈弄起来很麻烦么?,没搞定?
使用rvictl命令创建RVI接口(remote virtual interface),使用iPhone的UDID作为参数。
$ rvictl -s
如果想捕获多个设备的网络包,可以使用上述命令创建多个设备的RVI,传递每个iOS设备的UDID作为参数即可。
RVI虚拟接口的命名规则为rvi0,rvi1,rvi2,…,可使用ifconfig命令查看
$ ifconfig rvi0
rvi0: flags=3005 mtu 0
使用完之后需要将创建的虚拟接口移除
$ rvictl -x

使用tcpdump抓包
tcpdump -i rvi0 -w capture.cap -v -vv -c 100 -X -e

使用wireshark打开capture.cap就可以进行分析了

流量本来就可以通过instrument去看单进程的。。。。

testly #19 · June 08, 2015 作者

#18楼 @vigossjjj 你这个是network,都可以的

-_-#

文章排版有很多点乱,让我看了好伤

testly #22 · June 09, 2015 作者

#21楼 @lihuazhang 我再改改吧!

#1楼 @monkey 流量可以用charles 抓包

#23楼 @mobilefeng 这个不准的。只有部分的图片,api,而且是http的,非加密的那种才拿得到。

#23楼 @mobilefeng 另外,添加头像

#24楼 @monkey 新人 谢谢大大提醒~

赞,感谢分享!

能不能不用源码呢

testly #30 · August 06, 2015 作者

#28楼 @xiaoxiao 暂时不能把,看以后的趋势应该会有

@lihuazhang @testly 可以的吧,我们已经做出来了,不过性能不怎么好,我们是通过ssh在传数据,然后像android一样获取内存等信息,再通过Matlab来做图

#31楼 @xiaoxiao 可以发帖分享一下。记得@我哦!谢啦!

mark 收藏

可以自动化么

@testly 求教,现在启动时间那里,启动完后在sample list里搜索UIApplication _reportAppLaunchFinished结果为空,是什么原因呢?

#35楼 @jytest 我试了下,确实没找到。

我 google 了下,这篇文章也有提到这个方法,并有截图:http://www.programering.com/a/MTO4ATMwATU.html

文章中的图如下:

然而,我在 iOS 9.3 上对我自己的一个应用进行 profile ,结果却有出入:

调用栈有点不一样。文中调用的是 _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:,而我的是 _runWithMainScene:transitionContext:completion:

换了一台 iOS 7.1.2 的设备,调用栈和文章的一致了:

因此,估计文中的方法不适用于 iOS 9.3 。其它版本的系统目前手上没有,待其它同学测试。。。

至于 iOS 9.3 上应该以哪一帧作为启动结束,我也不清楚。。。 @testly 知道不?

testly #37 · May 21, 2016 作者

#36楼 @chenhengjie123 9.3 不是很清楚,我测得时候还是9.0以前

#31楼 @xiaoxiao 你好 请问一下你用代码是怎么实现获取iOS性能方面的数据的,如CPU。

testly #39 · November 23, 2016 作者

#38楼 @Mr.Tian 你好,OC有底层的API获取cpu 和内存 这种基础的性能数据,我这边的话因为要测竞品数据,所以用到了越狱手机,拿数据会方便很多

#39楼 @testly 我是用appium+python做自动化测试的,真机测试不知道怎么去获取这些数据,不知道楼主你有没有类似的资料。

testly #41 · November 24, 2016 作者

#40楼 @Mr.Tian 越狱设备可通过ssh获取基础性能数据,你自动化时可异步去截取数据

还是忧伤的问一句,图一那里打开的

testly #43 · April 20, 2017 作者
梦梦GO 回复

xcode debug session

向阳 利用 anyproxy 做 app 网络流量测试 中提及了此贴 17 Mar 14:15
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up