欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

IOS中判断卡顿的方案总结

程序员文章站 2022-09-23 10:10:35
fpsfps (frames per second) 是图像领域中的定义,表示每秒渲染帧数,通常用于衡量画面的流畅度,每秒帧数越多,则表示画面越流畅,60fps 最佳,一般我们的app的fps 只要保...

fps

fps (frames per second) 是图像领域中的定义,表示每秒渲染帧数,通常用于衡量画面的流畅度,每秒帧数越多,则表示画面越流畅,60fps 最佳,一般我们的app的fps 只要保持在 50-60之间,用户体验都是比较流畅的。

监测fps也有好几种,这里只说最常用的方案,我最早是在yyfpslabel中看到的。实现原理实现原理是向主线程的runloop的添加一个commonmodes的cadisplaylink,每次屏幕刷新的时候都要执行cadisplaylink的方法,所以可以统计1s内屏幕刷新的次数,也就是fps了,下面贴上我用swift实现的代码:

runloop

其实fps中cadisplaylink的使用也是基于runloop,都依赖main runloop。我们来看看

先来看看简版的runloop的代码

我们可以看到runloop调用方法主要集中在kcfrunloopbeforesources和kcfrunloopafterwaiting之间,有人可能会问kcfrunloopafterwaiting之后也有一些方法调用,为什么不监测呢,我的理解,大部分导致卡顿的的方法是在kcfrunloopbeforesources和kcfrunloopafterwaiting之间,比如source0主要是处理app内部事件,app自己负责管理(出发),如uievent(touch事件等,gs发起到runloop运行再到事件回调到ui)、cfsocketref。开辟一个子线程,然后实时计算 kcfrunloopbeforesources 和 kcfrunloopafterwaiting 两个状态区域之间的耗时是否超过某个阀值,来断定主线程的卡顿情况。

这里做法又有点不同,ios实时卡顿监控3 是设置连续5次超时50ms认为卡顿,戴铭在 gcdfetchfeed4 中设置的是连续3次超时80ms认为卡顿的代码。以下是ios实时卡顿监控中提供的代码:

子线程ping

但是由于主线程的runloop在闲置时基本处于before waiting状态,这就导致了即便没有发生任何卡顿,这种检测方式也总能认定主线程处在卡顿状态。这套卡顿监控方案大致思路为:创建一个子线程通过信号量去ping主线程,因为ping的时候主线程肯定是在kcfrunloopbeforesources和kcfrunloopafterwaiting之间。每次检测时设置标记位为yes,然后派发任务到主线程中将标记位设置为no。接着子线程沉睡超时阙值时长,判断标志位是否成功设置成no,如果没有说明主线程发生了卡顿。anreye5中就是使用子线程ping的方式监测卡顿的。

以下是我用swift实现的:

cpu超过了80%

这个是matrix-ios 卡顿监控提到的:

我们也认为 cpu 过高也可能导致应用出现卡顿,所以在子线程检查主线程状态的同时,如果检测到 cpu 占用过高,会捕获当前的线程快照保存到文件中。目前微信应用中认为,单核 cpu 的占用超过了 80%,此时的 cpu 占用就过高了。

这种方式一般不能单独拿来作为卡顿监测,但可以像微信matrix一样配合其他方式一起工作。

戴铭在gcdfetchfeed中如果cpu 的占用超过了 80%也捕获函数调用栈,以下是代码:

卡顿方法的栈信息

当我们得到卡顿的时间点,就要立即拿到卡顿的堆栈,有两种方式一种是遍历栈帧,实现原理我在ios获取任意线程调用栈7写的挺详细的,同时开源了代码rcbacktrace,另一种方式是通过signal获取任意线程调用栈,实现原理我在通过signal handling(信号处理)获取任意线程调用栈写了,代码在backtrace-swift,但这种方式在调试时比较麻烦,建议用第一种方式。

以上就是ios中判断卡顿的方案总结的详细内容,更多关于ios卡顿检测的资料请关注其它相关文章!