移动应用常见性能指标
要对应用开展性能测试,首先需要了解需要重点关注哪些指标?指标的参考范围大致是多少?可采用哪些工具收集这些指标?如何收集?如果指标有异常,大致有哪些high level的优化思路。这篇博客从cpu,内存,网络,其他,四个方面整理了移动应用常见指标以及参考值范围。具体如下图所示:(需要注意:指标数据范围仅供参考,以内存占用大小为例,国内很多app,实际应用大小都超过了200MB)
如何用Android Studio Profile分析应用性能
使用Android studio上运行移动应用,在工具最下面,会自动显示Profile工具菜单,如果没有看到这个菜单,还可以通过View/Tool Windows/中选择Profile工具。选择虚拟设备,以及选择应用后,就可以通过profile观察应用消耗的cpu,内存等信息了。
除了Android Profiler,还可以使用App Inspector观察应用的网络请求情况,数据库连接情况,后台任务情况等信息。通过收集这些信息进行性能评估。
在Android studio上还可以连接Firebase观察crash情况。在App Quality Inspect菜单中,选择Firebase,安装FireBase官网给出的配置建议完成配置后,即可通过FireBase观察应用Crash情况。
除了上面的性能数据收集分析工具,在Android studio中还可以查看logcat日志,查看应用运行过程中的异常信息,可帮助开发更好的进行分析。Android studio上的工具总体来将大部分都是白盒层面的工具,除了这些工具,实际还可以通过第三方黑盒类工具进行性能数据收集和分析。
如何用charles、wireshark等分析网络情况
如果要使用工具对移动应用进行抓包,大致可以分为三个步骤。步骤一:在工具上设置代理端口以及bypass的URL,这样所有通过这个端口的流量都会转发到代理工具上。步骤二:保证移动应用和电脑连接到相同的wifi上,这样可以保证通过内部IP地址访问时,可以相互访问,在手机上将电脑的内部IP地址+工具的代理端口设置为手机的代理,这样所有经过手机的流量,实际都会转发到电脑上安装的代理工具上。步骤三:下载证书,并在手机上信任证书,这样https的请求才能被解码显示。下面以charls和fidder为例子,简要演示如何通过抓包工具抓取移动手机上http/https请求。
步骤一:代理端口和规则设置
下面是Fidder的connections菜单的设置,这里代理的端口是8866,enable“Allow remote devices to connect”,Bypass URLs中增加了*,即所有的请求都被代理转发。
如果选用Charles来抓包,charles的默认端口是8888,这里也需要配置SSL proxying,增加了*,即所有的请求都被抓取并转发。
步骤二:移动手机上手动设置代理
在手机上设置代理前,首先需要知道电脑的内网IP,这个IP可以从代理工具上获取,以charles为例,在help菜单下,点击“Install Charles Root certification on a Mobile Device”,即可显示电脑的内网IP地址,当然,你也可以通过ifconfig命令获取IP地址。
在移动手机的wifi菜单下,手动设置代理的IP地址的端口,如下图所示:这里用的是Fidder的代理地址信息。设置代理后,所有的手机上的流量就能被抓包工具获取,并进行转发。
步骤三:下载安装证书,并信任证书
代理设置后,就可以按工具的提示信息,到指定web地址上下载证书,下载后安装,并信任证书。以Android手机为例,设置-安全-更多安全设置-加密与凭据-安装证书,选择刚才通过网站下载的证书,即可进行安装。安装完成后,在该目录还有个用户凭证的菜单,进入查看确保刚才的证书已经添加进去了。(需要注意一点:必须先设置代理,到chls.pro/ssl地址上才能下载证书。其他抓包工具如Fidder,HTTP toolkit等也是相同的步骤)
安装证书后,即可开始用Fidder或者Charls进行抓包了。在手机上访问移动app或者在浏览器上访问网站,在工具中会显示所有的https/http请求信息。下图是Fidder中抓取到的http请求信息,可以看到里面包含了整个请求耗费的时间,以及分段时间(即DNS time/TCP connect Time/HTTPS Handshake Time等),除时间外,还包括包的大小信息,通过这些信息,可以有效进行性能分析。
当然,除了Fidder,Charles也同样可以获取到https/http请求的时间,包大小等信息。具体如下所示:
对于https请求,为什么charles等工具可以进行解码呢?Charles和类似的中间人(Man-in-the-Middle, MITM)代理工具能够解密 HTTPS 请求的原因在于它们能够扮演客户端和服务器之间的中间人角色,通过安装自签名根证书来实现。以下是详细的解释其工作原理和具体步骤:
Charles 生成一个自签名的根证书,并要求用户在其设备上安装并信任这个根证书。当 Charles 代理 HTTPS 请求时,它会在客户端和目标服务器之间建立两个独立的 SSL/TLS 连接。对于每一个客户端请求,Charles 生成一个与目标服务器对应的伪造证书,这个伪造证书是用 Charles 的自签名根证书签名的。
Charles 与客户端建立 SSL/TLS 连接,并将自己伪装成目标服务器。因为客户端信任 Charles 的根证书,所以它会信任这个伪造的服务器证书。
同时,Charles 与目标服务器建立另一个 SSL/TLS 连接,并使用服务器的真实证书进行通信。Charles 代理解密从客户端发送到服务器的加密数据,然后将其转发到目标服务器。同样地,它解密从服务器返回到客户端的加密数据,再将其转发回客户端。
当然,如果请求数据是应用层加密的,Charles 或其他类似的工具无法直接解密这些内容。你需要应用本身的密钥和算法来解密,这通常是不可能的,因为这些信息对于普通用户来说是不可访问的。例如,抓取weixin的包,是无法看到包的request具体内容的,应该是weixin进行了请求数据层面的再次加密。
charles和fidder主要是抓取https/http请求,如果要对网络进行更加细致的分析,需要配合wireshark,wireshark是一个开源的抓包分析工具,对于https请求,wireshark不支持自动解密操作,这个部分可以用charles或者fidder解决。当开启了charles或者fidder一类的工具后,因为移动手机上的所有流量都会经过代理工具,所以开启wireshark,选择以太网端口抓取流量,即可抓取电脑上所有流量,再通过在过滤器中设置过滤来查看需要的分析的包信息。启动wireshark(这里为了不会有权限问题,使用sudo命令启动应用:sudo /Applications/Wireshark.app/Contents/MacOS/Wireshark)。在filter中通过设置ip地址为移动手机地地址来筛选出移动手机上的所有请求,然后进行分析。
当然,除了启动代理工具,来让wireshark抓取移动手机上流量包外,还可以在电脑上开启热点,手机连接到热点网络上,在启动wireshark时选择热点网路,也可以实现抓取移动手机上流量的效果。
如何用UIAutomator2进行巡检
除了上面的性能数据收集工具,还可以使用Android提供的UIAutomator2工具编写巡检代码。自动检查某些关键操作是否在期望时间内完成。例如,这里假设期望的所有操作都能在200ms内完成,下面代码调用Android提供的uiautomator2框架,对应用的一些需要检查的元素进行操作,并判断耗费的时间,将生成的结果存储到巡检报告文件中。为了测试更加稳定,也可以多次操作,求平均值,如果平均值在200ms内即可。
import uiautomator2 as u2
import time# 连接设备
d = u2.connect()# 定义关键元素的资源ID或其他属性
elements_to_check = [{"resourceId": "com.example:id/button1"},{"resourceId": "com.example:id/button2"},{"resourceId": "com.example:id/input_field"},{"resourceId": "com.example:id/submit_button"}
]def check_operation_timing(element):# 开始计时start_time = time.time()# 执行操作try:el = d(**element)if el.exists:el.click()else:print(f"元素 {element} 不存在")return False, 0except Exception as e:print(f"操作失败: {e}")return False, 0# 结束计时end_time = time.time()# 计算响应时间response_time = (end_time - start_time) * 1000 # 转换为毫秒# 检查响应时间是否在200ms以内if response_time <= 200:print(f"操作成功,响应时间:{response_time:.2f} 毫秒")return True, response_timeelse:print(f"操作超时,响应时间:{response_time:.2f} 毫秒")return False, response_timedef perform_inspection(elements):response_times = []for element in elements:success, response_time = check_operation_timing(element)if success:response_times.append(response_time)time.sleep(0.5) # 添加一些延迟,以避免设备过载return response_times# 进行巡检
response_times = perform_inspection(elements_to_check)# 统计结果
if response_times:average_time = sum(response_times) / len(response_times)print(f"平均响应时间:{average_time:.2f} 毫秒")
else:print("没有成功的操作")# 处理巡检结果,例如,保存到文件或数据库
以上就是在进行移动应用性能测试分析时,需要关注的常用指标以及一些常用工具的使用。