zoukankan      html  css  js  c++  java
  • iOS instruments trace文件解析方案

    前言

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

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

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

        故此,我觉得把整个流程记录下来,你可以认为这是一次iOS instruments的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文件恢复监控过程的柱状图,它给了我继续这个方向的信心。

        3KYW

         而从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:样本数据提取主流程。

    2016-03-28_114938

    深入Debug分析

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

         我需要解决的问题是:

         (1)确定instruments处理类。

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

         1. 确定instruments处理类

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

         E7I](3$)BP$K`K_XIIH6J77

         QQ图片20160328115512

        对比图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

         2. 读取trace样本数据

        (1)CPU样本结果

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

            N6ZL_F0OBPF9`4SHJH3G~)6

            TraceUtility使用了Undocumented API获取数据,而我在XRActivityInstrumentRun.h没找到相关API,直接通过反射获取吧。

            C59E220C-72B7-4C37-BE9A-C694A3025E66

            至此,CPU样本数据获取完成。

        (2)网络流量样本结果

        Y3GL1%)C3@72RR]E]00`Z52

        XRNetworkRun和XRActivityInstrumentRun对象属性不一样,没有_data,但_saveActivityQueries中有段sql,初步预估这玩意用了localdb,但db类型未明。另外,估计_saveInstrumentUUID应该db文件。

        然后cat 2A183EAD-5B9C-45DD-B2BA-D63DCD1165D4看下,因为文件可能会在头部加注类型信息,cat结果如下:

        X{2N8}OH$%VCG$F)`FBS9{6

        捕获SQLite文件一个……接下来的事情就是分析表结构了,没什么难度,不作详述了。至此,网络流量样本数据获取完成。

    --------------------我是一条的分割线--------------------

    补充部分-20160424

      关于以上代码,我的实施是在xcode7.2上,但到了xcode7.3,出现些坑爹问题:

      在调用PFTLoadPlugins时候,出现crash,如下:

      意思是,在xcode7.3后,PFTLoadPlugins()调用了applicationDirectoryName,但在调用applicationDirectoryName前,必须先调用initializeApplicationDirectoryName。而PFTLoadPlugins没有帮我们做init,所以呢,crash了!!!

      解决方案:自己动手调用.....

      (1)加载DVTFramework。

        位置:/Applications/Xcode.app/Contents/SharedFrameworks

        原因:initializeApplicationDirectoryName在该库中...

      (2)在.h文件增加

        @interface DVTDeveloperPaths : NSObject
          + (void)initializeApplicationDirectoryName:(id)arg1;
        @end

      (3)在main.m中,PFTLoadPlugins()前增加:

        id test = @"../../../../../../../Applications/Xcode.app/";
        [DVTDeveloperPaths initializeApplicationDirectoryName:test];

      完成以上步骤后,PFTLoadPlugins()可以正常执行!

  • 相关阅读:
    模板方法模式
    策略模式
    代理模式
    单例模式
    工厂模式
    服务器负载过高问题分析
    支付宝APP支付开发- IOException : DerInputStream.getLength(): lengthTag=89, too big
    阿里云linux服务器挂载数据盘
    3.3.4.2选择特定行
    3.3.4.1选择所有数据
  • 原文地址:https://www.cnblogs.com/hyddd/p/5329608.html
Copyright © 2011-2022 走看看