iOS instruments trace 文件解析方案

发表于:2016-05-11来源:测试窝作者:testerhome点击数: 标签:iOS
在 iOS 上做性能测试,Instruments 是必不可少的工具。然而由于苹果的封闭性,我们很难根据自己项目实际需要去修改它来获取自己想要的数据。

  在 iOS 上做性能测试,Instruments 是必不可少的工具。然而由于苹果的封闭性,我们很难根据自己项目实际需要去修改它来获取自己想要的数据。

  hyddd 通过自己的探索,找到了一条能获取一段时间内 App 的 CPU 占用和网络流量的路,并把自己探索的过程无私分享出来,填补了 iOS 自定义性能测试的一个空白,十分值得学习~

  前言

  已很少写文章,不过这次感觉有必要写一下。因为:

  1. 这个方案通过debug逆向得来,很有参考意义。

  2. iOS这方面资料非常少,做这块时,无论国内外,翻遍了google,baidu都没太多合适的资料

  故此,我觉得把整个流程记录下来,你可以认为,这是一次iOS的debug之旅。

  问题起因

  最近做iOS性能测试,要监控一段时间内App的CPU占用和网络流量。遗憾的是,iOS instruments提供的Activity Monitor和Network模板并不满足我的需求。在UI工具中,Activity Monitor只提供了CPU瞬时值,Network也只提供了总流量,它们均不提供采集样本值。

  由于iOS闭源,放出的资料又少,故解决此问题的方案屈指可数:

  (1). 设备越狱,通过后台守护进程采集数据。

  缺陷:新设备无法越狱。

  (2). 在产品中嵌入性能数据采集模块。

  缺陷:我不倾向在产品中嵌入测试模块;另外,该方案对第三方产品也失效。

  (3). 从instruments结果文件(.trace)中尝试获取样本值。

  缺陷:能不能做都不知道…

  因方案1,2有硬伤,故选方案3尝试。

  其实,我开始时也并不确定trace文件包含样本数据,但instruments可通过trace文件恢复监控过程的柱状图,它给了我继续这个方向的信心。

  而从trace文件获取样本值,有2个方向:

  (1)分析trace结构,获取明文数据

  trace其实是文件夹,但里面文件内容均为二进制,遂放弃......

  (2)通过Undocumented API解析trace文件

  由于instruments可以解析trace文件,那么(2)方法是一定可行的,问题是怎么找到相关的Undocumented API。

  Undocumented API可行性确认

  Lucky,我同事发现了这玩意:TraceUtility,它一个是获取Time Profiler样本值的工具(那作者也和我一样遇到这种蛋疼问题......),并且Readme中找到重要线索:

  (1)所需的Undocumented API在/Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/Frameworks:

  DVTInstrumentsFoundation.framework

  InstrumentsPlugIn.framework

  (2)Instruments模板以PlugIns形式存在于

  /Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns

  TraceUtility源码分析

  项目就2个文件:

  InstrumentsPrivateHeader.h: Undocumented API和Undocumented数据结构声明。

  main.m:样本数据提取主流程。

  深入Debug分析

  然而TraceUtility仅用于获取Time Profiler样本数据,并不能满足我获取CPU和网络流量样本的要求。

  我需要解决的问题是:

  (1)确定instruments处理类。

  (2)从处理类中读出样本数据。

  1. 确定instruments处理类

  方式很简单,在loadDocument后,debug变量trace._baseInstruments

  对比图1、2:

  XRSamplerInstrument=>XRSamplerRun

  XRActivityInstrument=>XRActivityRun?

  XRNetworkingInstrument=>XRNetworkingRun?

  在另一个github项目class-dump-o-tron, 搜到了相关信息:XRSamplerRun.h,然而在ActivityPlugin.xrplugin下却没找到XRActivityRun.h,而是 XRActivityInstrumentRun.h(大Apple的命名能统一点嘛……);在XRNetworkingPlugIn.xrplugin 下,找到了XRNetworkingRun.h;

  即最终对应关系:

  XRSamplerInstrument=>XRSamplerRun

  XRActivityInstrument=>XRActivityInstrumentRun

  XRNetworkingInstrument=>XRNetworkingRun

  2. 读取trace样本数据

  (1)CPU样本结果

  debug变量run._data,发现了样本数据

原文转自:http://www.testwo.com/article/654