iOS APP性能检测&优化(一)

性能优化,都要优化什么?

  • 启动时间
  • 内存
  • 刷新帧率
  • UI阻塞次数,不可操作时长,主线程阻塞超过400毫秒次数
  • CPU使用率
  • GPU使用率
  • 网络请求时间,流量消耗
  • 耗电功率

如何去监测这些性能指标。

  • Xcode自带的Instrument Instrument 用户指南(中文版)
    Instrument 性能检测图谱:

    Instrument 性能检测图谱.jpeg

  • 使用第三方SDK :Bugly、OneAPM、听云、Firebase Analytics

  • 自行开发检测代码

启动时间

1.通过Instrument的Time Profiler,找到包含-[UIApplication _reportAppLaunchFinished]的最后一帧,可计算出启动时间。

2.自行添加代码计算
t1
系统dylib和自身app可执行文件(app中所有.o文件的集合)的加载
Launch页

t2
main()
UIApplicationMain()
willFinishLaunchingWithOptions()
didFinishLaunchingWithOptions()

t3
loadView()
viewDidLoad()
applicationDidBecomeActive()

启动时间 t = t1 + t2;
app从启动到打开第一个页面的时间 t = t1 + t2 + t3;

t1:在Xcode的Edit scheme中增加
DYLD_PRINT_STATISTICS这个环境变量,控制台就会打印这个时间。


launch time.png

t2、t3都可以通过埋点的方式添加获取时间的代码即可。

内存

目前在开发的阶段只会注意内存泄露和内存异常两种情况,具体的内存分配、僵尸对象等可能会在开发结束后进行检测。

内存泄露除了使用instrument,还有:

  • 手动添加代码:
- (void)delloc {
      NSLog(@"------------->--->%@被释放了",[self class]);
}

这个只是说明某个类释放情况,并不能定位到具体代码,需要在类内部进行排查。

  • 第三方工具MLeaksFinder,优点:
    1.这个库不需要入侵项目代码,直接pod导入一下库就
    2.不用像instruments那么麻烦,还需要自己来仔细观察
    3.库只在debug状态运行,完全不影响app打包大小

内存异常就只是观察Xcode里面的内存显示或者埋点插入内存计算的方法,代码如下:

#import <mach/mach.h>
#import <mach/task_info.h>

- (unsigned long)memoryUsage
{
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);  
    if (kr != KERN_SUCCESS) {    
        return -1;
    }
    unsigned long memorySize = info.resident_size >> 10;//10-KB   20-MB   

    return memorySize;
//返回的数值单位是KB,如果想要MB的话把10改为20。
}

刷新帧率
刷新帧率利用CADisplayLink做一个小工具进行检测,查看认识并使用CADisplayLink

UI阻塞次数,不可操作时长,主线程阻塞超过400毫秒次数

美团移动端性能监控方案Hertz
在实践中采用的是检测主线程每次执行消息循环的时间,当这一时间大于阈值时,就记为发生一次卡顿。

卡顿检测.png

开辟一个子线程,然后实时计算 kCFRunLoopBeforeSources 和 kCFRunLoopAfterWaiting 两个状态区域之间的耗时是否超过某个阀值,来断定主线程的卡顿情况。这个还是比较准确的数据。
但是由于主线程的RunLoop在闲置时基本处于Before Waiting状态,这就导致了即便没有发生任何卡顿,这种检测方式也总能认定主线程处在卡顿状态。

CPU使用率
CPU使用率只需观察Xcode里面的数据或者埋点插入CPU使用率计算的方法,代码如下:

- (float)cpu_usage
{
    kern_return_t            kr = { 0 };
    task_info_data_t        tinfo = { 0 };
    mach_msg_type_number_t    task_info_count = TASK_INFO_MAX;

    kr = task_info( mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count ); 
    if ( KERN_SUCCESS != kr )   
        return 0.0f;

    task_basic_info_t        basic_info = { 0 };
    thread_array_t            thread_list = { 0 };
    mach_msg_type_number_t    thread_count = { 0 };

    thread_info_data_t        thinfo = { 0 };
    thread_basic_info_t        basic_info_th = { 0 };

    basic_info = (task_basic_info_t)tinfo;    // get threads in the task
    kr = task_threads( mach_task_self(), &thread_list, &thread_count ); 
    if ( KERN_SUCCESS != kr )   
        return 0.0f;  
    long    tot_sec = 0;  
    long    tot_usec = 0;  
    float    tot_cpu = 0;  
    for ( int i = 0; i < thread_count; i++ )
    {
        mach_msg_type_number_t thread_info_count = THREAD_INFO_MAX;

        kr = thread_info( thread_list[i], THREAD_BASIC_INFO, (thread_info_t)thinfo, &thread_info_count );   
         if ( KERN_SUCCESS != kr )       
              return 0.0f;

        basic_info_th = (thread_basic_info_t)thinfo;   
         if ( 0 == (basic_info_th->flags & TH_FLAGS_IDLE) )
        {
            tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
            tot_usec = tot_usec + basic_info_th->system_time.microseconds + basic_info_th->system_time.microseconds;
            tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE;
        }
    }

    kr = vm_deallocate( mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t) );  
           if ( KERN_SUCCESS != kr )    
               return 0.0f;   
            return tot_cpu * 100.; // CPU 占用百分比}

具体使用可以使用instrument查看。

GPU使用率
iOS 设备跟踪 GPU 使用率
GPUUtilization GPU使用率检测Demo

网络请求时间,流量消耗
该部分在AFNetworking研究之后再做补充。

链接文章:
iOS APP性能检测&优化(二)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容