iOS监控:资源使用

前言

应用性能的衡量标准有很多,从用户的角度来看,卡顿是最明显的表现,但这不意味看起来不卡顿的应用就不存在性能问题。从开发角度来看,衡量一段代码或者说算法的标准包括空间复杂度和时间复杂度,分别对应内存和CPU两种重要的计算机硬件。只有外在与内在都做没问题,才能说应用的性能做好了。因此,一套应用性能监控系统对开发者的帮助是巨大的,它能帮助你找到应用的性能瓶颈。

CPU

线程是程序运行的最小单位,换句话来说就是:我们的应用其实是由多个运行在CPU上面的线程组合而成的。要想知道应用占用了CPU多少资源,其实就是获取应用所有线程占用CPU的使用量。结构体thread_basic_info封装了单个线程的基本信息:

问题在于如何获取这些信息。iOS的操作系统是基于Darwin内核实现的,这个内核提供了task_threads接口让我们获取所有的线程列表以及接口thread_info来获取单个线程的信息:

第一个函数的target_task传入进程标记,这里使用mach_task_self()获取当前进程,后面两个传入两个指针分别返回线程列表和线程个数,第二个函数的flavor通过传入不同的宏定义获取不同的线程信息,这里使用THREAD_BASIC_INFO。此外,参数存在多种类型,实际上大多数都是mach_port_t类型的别名:

因此可以得到下面的代码来获取应用对应的CPU占用信息。宏定义TH_USAGE_SCALE返回CPU处理总频率:

内存

进程的内存使用信息同样放在了另一个结构体mach_task_basic_info中,存储了包括多种内存使用信息:

对应的获取函数名为task_info,传入进程名、获取的信息类型、信息存储结构体以及数量变量:

由于mach_task_basic_info中的内存使用bytes作为单位,在显示之前我们还需要进行一层转换。另外为了方便实际使用中的换算,笔者使用结构体来存储内存相关信息:

获取内存占用量的代码如下:

展示

内存和CPU的监控并不像其他设备信息一样,能做更多有趣的事情。实际上,这两者的获取是一段枯燥又固定的代码,因此并没有太多可说的。对于这两者的信息,基本上是开发阶段展示出来观察性能的。因此设置一个良好的查询周期以及展示是这个过程中相对好玩的地方。笔者最终监控的效果如下:

不知道什么原因导致了task_info获取到的内存信息总是比Xcode自身展示的要多20M左右,因此使用的时候自行扣去这一部分再做衡量。为了保证展示器总能显示在顶部,笔者创建了一个UIWindow的单例,通过设置windowLevel的值为CGFLOAT_MAX来保证显示在最顶层,并且重写了一部分方法保证不被修改:

三个标签栏采用异步绘制的方式保证更新文本的时候不影响主线程,核心代码:

其他

除了监控应用本身占用的CPU和内存资源之外,Darwin提供的接口还允许我们去监控整个设备本身的内存和CPU使用量,笔者分别封装了额外两个类来获取这些数据。最后统一封装了LXDResourceMonitor类来监控这些资源的使用,通过枚举来控制监控内容:

这里使用到了位运算的内容,相比起其他的手段要更简洁高效。APM系列至此已经完成了大半,当然除了网上常用的APM手段之外,笔者还会加入包括RunLoop优化运用相关的技术。

Demo在此

1 2 收藏 评论

关于作者:林欣达

iOS码农一枚 个人主页 · 我的文章 · 1 ·     

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部