利用RunLoop来监控APP的卡顿

深入探究RunLoop在iOS卡顿监控中的应用 在移动应用中,卡顿问题严重影响了用户体验,它通常表现为界面的响应迟缓,甚至出现短暂的无响应状态。比如用户在滑动屏幕、点击按钮或者动画播放时感觉到明显的延迟,这些都是卡顿的具体表现。如果一个应用经常出现卡顿,那么用户可能会对应用的稳定性和性能产生质疑,这直接影响了应用的可用性和口碑。卡顿是多方面因素造成的,它可以是由于系统资源不足、程序运行效率低、后台数据处理任务过重等原因造成的。用户对卡顿的容忍度较低,尤其在当今快节奏的使用环境中,卡顿问题很容易导致用户流失。在开发。 阅读详情

我们要怎么利用RunLoop的原理来帮我们定位到APP里面的卡顿场景呢?
人善,话不多,拿起键盘就开干。

从以下代码我们可以看出RunLoop的状态有六种,分别是进入RunLoop、处理timer之前、处理source之前、即将进入休眠、唤醒之后、退出RunLoop

    /* Run Loop Observer Activities */
    public struct CFRunLoopActivity : OptionSet {

        public init(rawValue: CFOptionFlags)
        public static var entry: CFRunLoopActivity { get } //进入RunLoop
        public static var beforeTimers: CFRunLoopActivity { get } //处理timer之前
        public static var beforeSources: CFRunLoopActivity { get } //处理source之前
        public static var beforeWaiting: CFRunLoopActivity { get } //即将进入休眠
        public static var afterWaiting: CFRunLoopActivity { get } //唤醒之后
        public static var exit: CFRunLoopActivity { get } //退出RunLoop
        public static var allActivities: CFRunLoopActivity { get } //所有状态
    }

我们可以通过beforeSources和afterWaiting这两个状态来监听卡顿,具体设置代码如下

    func startMonitor() {
        if self.observer == nil {
            self.start = true
            self.semaphore = DispatchSemaphore.init(value: 1)
            //启动一条子线程来监听卡顿
            Thread.detachNewThreadSelector(#selector(subThread), toTarget: self, with: nil)
                        
            //创建观察者
            var context = CFRunLoopObserverContext.init(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
            self.observer = CFRunLoopObserverCreate(kCFAllocatorDefault, CFRunLoopActivity.allActivities.rawValue, true, 0, {(observer, activity, pointer) in
                //RunLoop状态改变的回调               			MonitorManager.manager.RunLoopActivity = activity
                MonitorManager.manager.semaphore?.signal()
            }, &context)
            //将观察者添加在主线程RunLoop的commonModes模式下面
            CFRunLoopAddObserver(CFRunLoopGetMain(), self.observer, CFRunLoopMode.commonModes)
        }
    }

    @objc func subThread() {
        while self.start! {
            //这里设置的阈值为500毫秒。阈值不宜设置的太小,太小会检测到一些用户无感的卡顿。也不宜设置的太大,太大了则会错过一些明显的卡顿
            let wait = self.semaphore?.wait(timeout: .now() + 0.5)
            if wait == DispatchTimeoutResult.timedOut {
                if self.observer != nil {
                    if (self.RunLoopActivity == CFRunLoopActivity.beforeSources || self.RunLoopActivity == CFRunLoopActivity.afterWaiting) && self.start == true {
                        /*
                         这里检测到卡顿,可以打印堆栈信息查看是在调用哪些方法的时候导致了卡顿。也可以利用PLCrashReporter这个第三方库来协助我们打印堆栈信息。我们需要把堆栈信息发送到服务器以便分析问题
                         */
                        print("卡顿了")
                    }
                }
            }
        }
        print("子线程销毁了")
    }

来说一下阈值的取值范围。阈值不宜设置的太小,太小会检测到一些用户无感的卡顿。也不宜设置的太大,太大了则会错过一些明显的卡顿。
个人认为,如果想把APP的流畅度优化到很好可以把阈值设置为毫秒级别的,如果只想解决用户能明显感知到的卡顿可以把阈值设置为秒级别的。(这里只是个人的观点,如果有误还望指出)

接下来我们来看一下运行的效果,在UITableViewCell滚动到50行的时候让程序进入睡眠1秒来模拟卡顿,结果如下图所示
在这里插入图片描述
如你所见,在滚动到50行的时候检测出了卡顿。

好了,这次的文章到这里就结束了。如果有说的不当的地方还望各路大神指出。
最后附上GitHubDemo

利用RunLoop监控卡顿 利用RunLoop监控卡顿的demo,对应博客:https://blog.youkuaiyun.com/dolacmeng/article/details/89343075 立即下载

相关推荐

MainThreadRunloopMonitor:主线程Runloop状态检测的一个演示

MainThreadRunloopMonitor 主线程Runloop状态检测的一个演示

iOS卡顿优化检测

一般写代码过程中容易造成卡顿的问题就是主线程存在一些耗时操作,例如数据库操作,图片的处理,大量数据的处理等。在日常编码过程中要养成习惯,将一些耗时操作放在并发队列中异步执行,这样可以避免很多卡顿的问题。

liuxinzhongliubin的博客 2096

PR控制以及使用PR控制用于单相离/并网逆变器

最近想学习一下并网逆变器,需要用到PR控制,全网找遍了许多学习资料,终于掌握的差不多了,在此做个记录,以及个人对PR(Proportional Resonant)控制的理解。在去年7月准备电赛的时候偶然看到有几篇讲解数字滤波器,第一次接触传递函数离散化,深刻被数字时代的数字方式折服,改改代码,就可以实现不同的截至频率,甚至不同阶数,而模拟方式还要改元器件。当时就感觉这玩意太他妈牛逼了,很想学懂它,奈何学不会呀。后面全身心做电赛,就忘了这事儿。直至最近学习PR控制,当初的感觉又回来了,一股劲儿吃下来了。

xht2403267701的博客 3万+

iOS之卡顿检测

很多iOS 开发,开发过程中都会面临到解决App卡顿问题,从而也衍生出很多的方法去解决卡顿,这篇文章来描述下iOS卡顿产生的原因,以及如何进行iOS卡顿检测分析。像素是如何显示到屏幕上?从最初的电子枪显示器说起,电子枪逐行读取像素点,逐行发射到屏幕上,每当一行扫描完成,显示器会发出水平同步信号HSync;然后继续下一行,直到最后一行完成一帧的绘制,电子枪恢复到起点继续下一帧的绘制,显示器会发出一个垂直同步信号VSync。对于iOS设备,VSync信号的间隔是16.7ms,也就是1秒60帧。实际绘制过程中:1

wywinstonwy的专栏 3874

硬全桥副边钳位管Vds电压凸台揭秘——寄生参数引发的导通异常

本文深入分析了硬全桥副边钳位管Vds电压凸台现象,揭示了寄生参数如何引发导通异常。通过波形分析和工程实践,详细解析了走线电感的蓄能效应和体二极管的接力作用,并提供了PCB布局优化、元件选型和驱动电路调整等解决方案,帮助工程师有效应对这一常见问题。

weixin_30825581的博客 430

【Anaconda】conda国内镜像源快速配置指南(清华/阿里云)

本文详细介绍了如何为Anaconda配置国内镜像源(清华/阿里云),以显著提升conda包下载速度并减少安装失败率。通过分步指南和实用技巧,帮助开发者快速完成配置,优化Python开发环境。

weixin_33725722的博客 1488

iOS中的3种卡顿检测

市面上的iOS卡顿分析方案有三种:监控FPS、监控RunLoop、ping主线程。 前面2个都比较熟悉,第三个是最近才了解到的。 方案一:监控FPS 一般来说,我们约定60FPS即为流畅。那么反过来,如果App在运行期间出现了掉帧,即可认为出现了卡顿。 监控FPS的方案几乎都是基于CADisplayLink实现的。简单介绍一下CADisplayLink:CADisplayLink是一个和屏幕刷新率保持一致的定时器,一但 CADisplayLink 以特定的模式注册到runloop之后,每当屏幕需要刷

gcs的博客 6145

优惠券管理

(请设计一个优惠券兑换码生成方案,可以支持20亿以上的唯一兑换码,兑换码长度不超过10,只能包含字母数字,并且要保证生成和校验算法的高效)最后把签名值的后14位、新鲜值(4位)、自增序列(32位)拼接,得到一个50位二进制数,然后与一个较大的质数做异或运算加以混淆,再基于Base32或Base64转码,即可的对兑换码。现在,就剩下防止爆刷了。自增id从1增加到Integer的最大值,可以达到40亿以上个数字,而占用的字节仅仅4个字节,也就是32个bit位,距离50个bit位的限制还有很大的剩余,符合要求!

qq_36312661的博客 2206

RunLoop卡顿监控

卡顿主要表现为主线程卡死,不响应用户动作或者响应很慢,这种体验很差,会让用户对产品的认可度急速下滑,如果不及时优化,最终会导致用户流失。 那么,哪些情况会导致主线程卡顿呢?大体有如下几个方面: 很复杂的 UI 、图文混排的绘制量很大; 主线程进行网络同步请求; 主线程上做大量的 IO 操作; 运算量过大,CPU 持续高占用; 死锁和主子线程抢锁。 检测方案 为了优化卡顿,我们需要准确的知道哪里发生了卡顿,然后才能有针对性的进行优化,所以在开始优化之前我们需要去监控卡顿发生的地方。那么问题来了,怎么监控卡

Jerod's blog 404

AFSim 2.9中文手册实战指南:从安装到高级功能详解(附B站视频链接)

本文详细介绍了AFSim 2.9的安装配置、基础功能操作和高级功能应用,帮助用户快速掌握这款强大的仿真平台。从系统要求检查到多体动力学仿真,再到性能优化技巧,全面解析AFSim 2.9的使用方法,适合初学者和进阶用户参考。

weixin_30892037的博客 568

【运动规划算法项目实战】全覆盖分区算法

全覆盖规划在机器人学领域具有重要意义,其应用场景涵盖了自动农场、扫地机器人、扫描监视无人机等多个领域。该问题的核心目标是使机器人能够从指定起点出发,规划一条避开障碍物、同时路径尽可能短的轨迹,从而实现对特定区域的全面覆盖。在实际应用中,全覆盖规划的成功实现对于提高机器人在各类环境中的工作效率至关重要。这一问题的解决涉及到高效的路径规划和规划区域分解技术。其中,梯形单元分解算法是一种常用分区的技术,过将地图上需要规划的区域进行分区,采用梯形分解的方式,可以更好地应对复杂环境。全覆盖算法规划流程。

xiewf的博客 1万+

Runloop监控卡顿

Runloop监控卡顿 主线程主要用来处理UI绘制、更新以及与用户的交互事件,如果任务占用主线程,用户会感觉到界面卡顿或者app没反应。 思路:线程的消息事件依赖于NSRunloop,它们关系如下 线程与RunLoop是一一对应的,并通过全局的字典保存对应关系 线程如果没有开启RunLoop, 任务执行完就会结束 线程销毁了,RunLoop也会在线程结束时停止运行 所以监听主线程的卡顿可以转换为监听NSRunloop的状态,runloop的状态有六个,分别是 typedef CF_OPTIONS(CFO

onebutterfly 1059

AutoSAR系列讲解(实践篇)7.3-AppL在Dev中的配置(下)

接着讲解Dev中剩下的几个定义项

雪云飞星的博客 1万+

23、RunLoop学习

RunLoop学习RunLoop的本质为什么main函数可以保持一直运行不退出RunLoop数据结构CFRunLoopCFRunLoopModeSource/Timer/OberserverCFRunLoopSourceCFRunLoopTimerCFRunLoopObserver各个数据结构之间的关系RunLoop的ModeRunLoop事件循环的实现机制点击一个app图标打开app到app杀死,经历了哪些过程RunLoop与NSTimer滑动TableView的时候,我们的定时器还会生效吗?RunLoo

重楼的博客 753

详解Agent Skills:让AI拥有更多专业能力(什么是Agent Skills?如何创建?如何使用?如何获取?)

本文分享如何将零散指令沉淀为可复用的 AI 能力模块🧩,介绍什么是Agent Skills?如何创建?如何获取?📚

XiaoqiangClub的博客 1271

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

子程序调用编程序例子_iOS 如何抓取线程的“方法调用栈”?

场景:在一些 “性能监控” 的工具中,在检测到App主线程卡顿的时候,可以通过子线程抓取当前时刻所有线程的方法调用堆栈(保存卡顿现场),并在合适的时机(WiFi环境&网络环境较好的时候)把堆栈信息上传到我们的服务端。服务端将堆栈信息过滤分析后,交给客户端做优化处理。 这样,就能较好的提高用户的体验,并及时发现线上环境下的问题。同时,也可以及时发现问题,及时优化我们的代码质量和执行效率。(一...

weixin_39845461的博客 464

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

如何利用 RunLoop 原理去监控卡顿?

卡顿问题,就是在主线程上无法响应用户交互的问题。如果一个 App 时不时地就给你卡一下,有时还长时间无响应,这时你还愿意继续用它吗?所以说,卡顿问题对 App 的伤害是巨大的,也是我们必须要重点解决的一个问题。 现在,我们先来看一下导致卡顿问题的几种原因: 复杂 UI 、图文混排的绘制量过大; 在主线程上做网络同步请求; 在主线程做大量的 IO 操作; 运算量过大,CPU 持续高占用; 死锁和主子线程抢锁。 那么,我们如何监控到什么时候会出现卡顿呢?是要监视 FPS 吗? RunLoop 原理

eastWind1101的博客 1276

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

iOS 之如何利用 RunLoop 原理去监控卡顿?

【优快云 编者按】简单来说APP卡顿,就是FPS达不到60帧率,丢帧现象,就会卡顿,但是很多时候,我们只知道丢帧了,具体为什么丢帧,却不是很清楚,那么我们要怎么监控呢?作者 | 枫叶无处...

优快云资讯 1646

如何用RunLoop检测iOS App 卡顿

首先本文的思路来自于网上的各种资料。然后搜了半天发现没有swift版的,于是撸了一个。 其实具体的思路非常的简单: 首先创建一个runloop的observer对象: let info = Unmanaged<Monitor>.passUnretained(self).toOpaque() var context: CFRunLoopObserverContext = CFRu...

weixin_34376562的博客 661

iOS八股文之 RunLoop

iOS RunLoop 是管理线程事件循环的核心机制,通过Mode隔离不同场景的事件源(Sources0/1、Timers、Observers),实现"按需唤醒、隔离事件"。主线程RunLoop自动运行,子线程需手动启动。RunLoop关键应用包括:解决NSTimer滑动失效(CommonModes)、子线程保活(添加Port事件源)、滑动时暂停非必要任务优化性能。理解RunLoop对多线程编程、性能优化和卡顿监控至关重要。

RollingPin的博客 1284

【iOS开发】RunLoop总结:RunLoop的应用场景(四)App卡顿监测

RunLoop总结:RunLoop的应用场景(四)App卡顿监测 微信iOS卡顿监控系统

Hanrovey Blog 701

带你打造一套 APM 监控系统 之 卡顿监控

Python实战社群Java实战社群长按识别下方二维码,按需求添加扫码关注添加客服进Python社群▲扫码关注添加客服进Java社群▲作者丨杭城小刘来源公众号丨知识小集(zsxjtip)...

iOS_开发 656

iOS 页面卡顿排查:RunLoop 机制 + 渲染帧率监控 + UI 绘制优化

优先解决离屏渲染和 CPU 密集计算,保持单帧处理时间 ≤16ms。通过 RunLoop 监控定位阻塞点,结合帧率数据制定优化策略,可系统性解决卡顿问题。

2501_93878564的博客 375

Runloop机制解析及应用

- Runloop学习背景 在调研卡顿监控的过程中,接触到了Runloop机制及其用法,其中一种方案是通过监听每次Runloop循环的时间来判断是否出现时间的阻塞,并同时dump出正在执行的调用栈来定位执行时间较长的函数,进一步进行优化。同时还有通过开启另外的线程给主线程发送消息,看主线程Runloop是否能够处理Source事件来进行处理返回的时间来判断阻塞状况。 - RunLoop定义 在...

TuGeLe的博客 700

监控主线程耗时_iOS性能优化 — 二、卡顿监控及处理

上篇文章为大家讲解了crash监控及防崩溃处理,这片文章继续为大家讲解下卡顿监控及处理。卡顿产生原理如何收集卡顿利用bugly、听云等第三方收集自己收集卡顿监控主线程RunLoop子线程ping卡顿产生原理FPS (Frames Per Second) 表示每秒渲染帧数,通常用于衡量画面的流畅度,每秒帧数越多,则表示画面越流畅。通常60是临界值,如果主线层FPS低于60fps,应用程序就可能产生卡...

weixin_35034536的博客 470

监控主线程耗时_iOS 性能优化 二、卡顿监控及处理

这片文章继续为大家讲解下卡顿监控及处理。 卡顿产生原理 如何收集卡顿 * 利用bugly、听云等第三方收集 * 自己收集卡顿 * 监控主线程RunLoop * 子线程ping卡顿产生原理FPS (Frames Per Second) 表示每秒渲染帧数,通常用于衡量画面的流畅度,每秒帧数越多,则表示画面越流畅。通常60是临界值,如果主线层F...

weixin_29237635的博客 300
下一篇: 简单实用的无痕埋点方案
菜鸟的向往
博客等级 码龄10年 1粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值