iOS性能监控

CPU 监控

CPU是移动设备最重要的计算资源,如果CPU持续高负载运行,一方面会导致用户使用过程遭遇卡顿,另一方面也会使手机发热发烫,电量被快速消耗完,严重影响用户体验

避免之上情况出现,可通过监控应用的CPU占用率

Q:CPU占用率如何监控呢?

A:线程CPU是调度和分配的基本单位,而应用作为进程运行时,包含了多个不同的线程,如果能知道app里所有线程占用CPU的情况,也就能知道整个APP的CPU占用率。

iOS 是基于 Apple Darwin 内核,由 kernel、XNU 和 Runtime 组成,而 XNU 是 Darwin 的内核,它是“X is not UNIX”的缩写,是一个混合内核,由 Mach 微内核和 BSD 组成。Mach 内核是轻量级的平台,只能完成操作系统最基本的职责,比如:进程和线程、虚拟内存管理、任务调度、进程通信和消息传递机制。其他的工作,例如文件操作和设备访问,都由 BSD 层实现。

引用自:《OS X and iOS Kernel Programming》 中对Mac OS X 中进程子系统组成的概念图

iOS的线程技术也是基于Mach线程技术实现的,在Mach层中thread_basic_info结构体中发现了我们想要的东西

thread_basic_info

cpu_usage 对应线程的CPU使用率

任务(task)是一种容器(container)对象,虚拟内存空间和其他资源都是通过这个容器对象管理的,这些资源包括设备和其他句柄。严格地说,Mach 的任务并不是其他操作系统中所谓的进程,因为 Mach 作为一个微内核的操作系统,并没有提供“进程”的逻辑,而只是提供了最基本的实现。不过在 BSD 的模型中,这两个概念有1:1的简单映射,每一个 BSD 进程(也就是 OS X 进程)都在底层关联了一个 Mach 任务对象

Mach task 可以看作一个机器无关的 thread 执行环境的抽象

一个 task 包含它的线程列表。内核提供了 task_threads API 调用获取指定 task 的线程列表,然后可以通过 thread_info API 调用来查询指定线程的信息,thread_info API 在 thread_act.h中定义

task_threads

task_threads 将 target_task 任务中的所有线程保存在 act_list 数组中,数组中包含 act_listCnt 个条目

thread_info

thread_info 查询 flavor 指定的 thread 信息,将信息返回到长度为 thread_info_outCnt 字节的 thread_info_out 缓存区中


Memory监控

物理内存(RAM)与CPU一样都是系统中最稀少的资源,也是最有可能产生竞争的资源,应用内存与性能直接相关

由于iOS中没有交换空间作为备选资源,使得内存资源尤为重要(通常是以牺牲被的应用为代价)

Q:如何APP占用的内存?

A:获取app内存的API同样可以在Mach层找到,mach_task_basic_info结构体存储了Mach task的内存使用信息

mach_task_basic_info 结构体存储了 Mach task 的内存使用信息,其中 resident_size 就是应用使用的物理内存大小,virtual_size 是虚拟内存大小

mach_task_basic_info

值得注意的是task_basic_info在 Apple 已经不建议再使用,而是使用mach_task_basic_info

task_info

task_info API 根据指定的 flavor 类型返回 target_task 的信息


FPS监控

FPS 是测量用于保存、显示动态视频的信息数量,每秒钟帧数愈多,所显示的动作就会愈流畅,一般应用只要保持 FPS 在 50-60,应用就会给用户流畅的感觉,反之,用户则会感觉到卡顿

主要是基于CADisplayLink以屏幕刷新频率同步绘图的特性,尝试根据这点去实现一个可以观察屏幕当前帧数的指示器

主要原理:

1、CADisplayLink 默认每秒60次

2、将CADisplayLink add到 mainRunLoop中

3、使用CADisplayLink的timestamp属性,在CADisplayLink每次tick时,记录上一次timestamp

4、用_count记录CADisplayLink tick的执行次数

5、计算此次tick时,CADisplayLink的当前timestamp和_lastTime的差值delta

6、如果差值大于1,fps=_count/delta,计算得出FPS数

值得注意的是基于CADisplayLink实现的 FPS 在生产场景中只有指导意义,不能代表真实的 FPS,因为基于CADisplayLink实现的 FPS 无法完全检测出当前 Core Animation 的性能情况,它只能检测出当前 RunLoop的帧率


Thread(主线程卡顿监控)

当监控到应用出现卡顿,如何定位造成卡顿的原因呢?试想如果能够在发生卡顿的时候,保存应用的上下文,即卡顿发生时程序的堆栈调用和运行日志,那么就能凭借这些信息更加高效地定位到造成卡顿问题的来源

监控界面卡顿,主要是监控主线程做了哪些耗时的操作,(之前分享渲染流程时提到过卡顿),iOS中线程的事件处理依靠的是RunLoop,正常FPS值为60,如果单次RunLoop运行循环的事件超过16.66ms,就会使得FPS值低于60,如果耗时更多,就会有明显的卡顿

runloop观察者: Runloop Observer有7种状态 (CF-1151.16版本)

runloop


runloop工作原理(图片来自网络)

    input sources : 传递异步事件, 通常消息来自于其他线程或程序.

    timer sources : 传递同步事件, 发生在特定时间或者重复的时间间隔.

    当sources到来的时候, 唤醒RunLoop, 该干嘛干嘛. 具体流程可如下所示 :

runloop流程(图片来自网络)

Apple源码具体实现在CF框架中,CFRunloop.c中 __CFRunLoopRun方法可查看(可自行下载看)

从运行循环中可以看出,RunLoop休眠的事件是无法衡量的,处理事件的部分主要是在kCFRunLoopBeforeSources之后到kCFRunLoopBeforeWaiting之前和kCFRunLoopAfterWaiting 之后和运行循环结束之前这两个部分

监控这两个部分的耗时,使用CFRunLoopObserverRef来监控RunLoop的状态

需要注意的是,对卡顿的判断是通过kCFRunLoopBeforeSources或者kCFRunLoopBeforeWaiting这两个状态开始后,信号量+1,这时候信号量>0,dispatch_semaphore_wait不会阻塞,返回0,进行下一个while循环,如果此时还没有进入下一个RunLoop状态,此时信号量=0,dispatch_semaphore_wait就会在这里阻塞,到了设定的超时时间,dispatch_semaphore_wait的返回值>0,这时候就会进行耗时的判断。我们可以自己设定超时时间和超过多少次算卡顿,比如:设置超过250ms


具体代码实现下载地址

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

推荐阅读更多精彩内容