本文主要介绍Heimdallr对卡死、卡顿异常的监控原理,并结合长时间的业务沉淀发现的问题进行不断迭代和优化,逐步实现全面、稳定、可靠的历程。

作者:字节跳动终端技术——白昆仑

前言

卡死、卡顿作为目前iOS App的重要线程和进程的区别是什么性能开源阅读指标,不仅影响着用户体验,更关系到用户留存、DAU等重要产品数据。本文主要介绍Heimdallr对卡死、卡顿异常的监控原理,并结合长时间的业务沉淀发现开源矿工的问题进行不断迭代appstore和优化,逐步实现全面、稳定、可靠的历程。

一、什么是卡死/卡顿?

卡顿,顾名思义就是在使用过程中出现了一段时间的阻塞,使得用户线程数在这一段时间内无安全中心法进行操appearance作,屏幕上的内容也没有任何的变化安全Hei开源软件mdappleallr在监控指标开源中国上,根据阻塞时间的长短进行了3个线程是什么意思等级的划分。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

1、流畅性与丢帧:动画、滑动列表不流畅,一般为十几至几十毫秒的级别

2、卡顿:短时间操作无反开源矿工应,恢复后能继续使用,从几百毫秒至几秒

3、卡死:长时间无反应,approach直至被系统杀线程是什么意思死,通过线上收集数据,最少为5s

可以看到,根据严重性由小至大可将卡顿问题划分为流开源阅读app下载安装畅性与丢帧、卡顿、卡死三个不同的等级。卡死的严重程度与Crash是相当的,甚至更为严重。因为卡死不仅仅造成了类似于崩溃的闪退,更使得用户被迫等待线程了相当长的一段时间,更加损害用户的体验。由于监控方案上的差异,本文主要面向的是后两者卡顿和卡死的监控。

二、卡死/卡顿的原因

iOS开发中开源阅读,由于UI线程和进程的区别是什么Kit是非线程安全的,因此一切与UI相关的操作都必须放在主线程执行,系统会每16ms(1/60帧)将UI的变化重新绘制,渲染至屏幕上。如appear果UI刷新的间隔能小于16ms,那么用户是不会感到卡顿的。但是如果在主线程进行了一些耗时的操作,阻碍了UI安全工程师的刷新,那么就会产生卡顿,甚至是卡死。主线程对于任务的处理是基于Runloop机制,如下图所示。Runloop支持外部注册通知回调,提供了

1、RunloopEntry

2、Ru线程阻塞nloopBeforeT线程的几种状态imers

3、RunloopBeforeSources

4、RunloopBeforeWaitiappreciateng

5、线程安全RunloopA开源节流fterWaiting

6、RunloopExit

6个时机的事件回调,其流转开源阅读app下载安装关系如下图所示。Runloop在没有任务需要处理的时候就会进入至休眠状态,直至有信号将其唤醒,其又会去处理新的任务。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

在日常编码中,UIEvent事件、appstoreTimer事件、dispatch主线程任务都是在Runloop的循环机制的驱动下完成的。一旦我们在主线程中的任何一个环节进行了一个耗时的操作,或者因为锁的使用不当造成了与其它线程的死锁,主线程就会因为无法执行Core - Animation的回调而造成界面无法刷新。而用户的交互又依赖于开源矿工UIEvent的传递和响应,该流程也必须在主线程中完成。所以说主线程appreciate的阻塞会导致UI和交互的双双阻塞,这也是导致卡死、卡顿的根本原因。

三、开源阅读app下载安装监控方案

既然问线程池题的根本在于主线程Runloop的阻塞,那么我们就要通过技术手段监测主线程Runloop的运行状态。为了能够实时获取主线程Runloop的状态,首先对主线程注册上面提到的几个事件回调,在触发事件回调时,利用signal机制将其运行状态传开源阅读app下载安装递给另一个正在监听的子线程(后面称之为监听线程)。监听线程对appointment于信号的处理可以是多样的,它可以设置等待signal的超时时间,如果超过了设定的阈值,这说明主线程可能正在经历阻塞。通过监听线程,我们appointment可以完整地了解到主线程Runloop循环的周期,目前处开源节流于哪个阶段,耗时了多久等等。根据这些必要的信息,就可以采取对应的策略进行异常的捕获和处理,后面会单独就卡顿、卡死分别进行说明。

目前大多数APM工具都是采用监听Runloo线程数p的方式进行卡顿的捕获,这也是性能、准确性表现最好的一种方案。由于RunloopBefo安全reTimers的和RunloopBeforeSources是紧邻的两个事件回调,H安全教育平台登录eimdal安全教育平台登录lr为了降低Runloop频繁事件回调造成的性能损失,去除了对RunloopBeforeTimers的监听。

  1. 卡顿(ANR)

卡顿监控的特点线程池的七个参数在于主线程的阻塞是暂时的、能够恢复的,因线程撕裂者此我们要获取卡顿持续的时间,用来评估卡顿问题的严重性。我开源是什么意思们预先设定一个卡顿时间的阈值T,当主线程阻塞的时间超过该阈值,则会触发全线程的抓栈,获取卡顿场景线程的堆栈信息。此后监听线程继续等待主线开源节流什么意思程直至主线程恢复,并计算卡顿的总时间,整合之前获取的堆栈信息,上报卡顿异安全常。需要说明的是,如果在抓栈之后主线程无法恢复,那么该异常不是卡顿,应交由卡死模块处理。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

  1. 卡死(WatchDog)

与卡安全生产法顿不同,卡死的阻塞是更长的,而且是无法恢复的。iOS系统会对App的主线程进行类似的监控,一旦发现了阻塞的情况,持续时间大于当前系统内允许的阈值(不同iOS版本和开源中国机型不同),就会强制杀死当前App进程,这个操作是没有任何通知的。因此我们需要做的就是在系统发现卡死并强杀之前,获取堆栈,并尽可能的开源软件评估安全期计算器出卡死持续的时间。

预先设定一个卡死的阈值T(默认是8s),这个阈值可以是相对保守的,并不是说超过了这个阈值就一定会被判定为卡死。在超过卡死阈值T的时候,获取全线安全期计算器程的apple堆栈,并保存至本地文件中。之后每隔一段时间(采样间隔,默认是1s),会进行一次采样。采样的目的不是为了获取新的堆栈,线程的几种状态而是为了更新卡死持续的时间安全生产法,将该信息线程的几种状态保存至本地文件中。因此,采样的间隔越开源众包小逼近真实卡死时间按越精确。直至到某一个时间节点,系统把App杀死。当App下一次启动时,卡死模块会根据上一次启动中保留的本地文件信息,还原出卡死的堆栈、持续时间等信息,并上报卡死异常。

需要说明的是,很多人线程认为卡死一定是因为死锁、死循环这样的场景,导致程序永远也无法完成导致的。其实不然,在很多场景下,一个或多个耗时的操作,只要其耗时超过了系统的允许阈值,都会触发卡死approach。当应用启动过程中,没有在限定apple苹果官网时间内完成初始化工作也会被系统杀死。所以,某些卡死可能是多个app小胖子场景的不合线程阻塞理一起导致的,这也给卡死的问题定位提出了更高的要求。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

四、问题与优化

理想是丰满安全教育平台的,现实是骨感的安全教育。看似”无懈可击“的监控方案,在线上却暴露出不同程度的问题。

  1. 卡顿监控优化

在卡顿监控中开源阅读app下载安装,我们认为超过了卡顿阈值时安全工程师获取的堆栈一定是一个卡顿的场景,其实不然。在一些时候,获取的堆栈可能是他人的”背锅侠“。我们来看线程的概念下面这个case开源中国。导致主线程卡顿的是4这app小胖子个耗时操作,但是当我们设定阈值超时时,获取的堆栈却是没有任何性能问题的5。因此如果使用这线程阻塞种方式来进行卡顿的监控,一定会存在误报。而根据概率来讲,虽然上报的5是一个误报,但就线上的上报量来讲,4的数量一定是要大于5的。因此上报量级大的堆栈才应该是真正的耗时操作,是需要我们专注去解决的,而那开源阅读app下载安装些量级较小的堆栈则可能是误报。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

线程的概念么是否能够通过一些技术手段,在控制性能开销的情况下,对卡顿场景捕捉的更加准确呢?开源代码网站github一个比较好的思路就是采样策略。如下图,我们在原有的”常规模式“的基础上增加了”线程阻塞采样模式“。需要额外定义采样app小胖子间隔、采样线程安全阈值。我们把卡顿阈值的等待过程,划分为以采样间隔为单位的粒度更细的时间节点线程数越多越好吗。在每个时间节点进行主线程采样,对主线程进行堆栈的提取。安全教育平台登录入口由于仅对主线程进行堆栈提取,所以耗时APP较全开源中国线程抓栈appreciate要小很多。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

获取了主线线程数越多越好吗程堆栈后,通过提取顶层第一个自身调用来进行堆栈的安全聚合。如果某一个相同堆栈持续的线程是什么意思时间超过了设定的采样阈值,例如图中的4,重复了3次,那么就会判定该场景一定是一个卡顿场景。那么此时就会进行全线程抓栈,而后面的卡顿阈值触发时则不再抓栈。

结合主线程采样,我们可以更加精准的以函数级别监控卡顿场景,但是也需要付出采样带来的额外性能开销。为了将采样的开销降至最低,避免线上对低端设备造application成二次性能劣化,卡顿监控支持采样功能的退火策略。当某一个卡顿场景被多次捕获时,为了避免再次将其捕获,造成不必要的性能浪费,会逐步增线程和进程的区别是什么加采样间隔,直至将”采样模式“退化成”常规模式“。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

在Slardar平台配置并开启采样功线程池的七个参数能后,可以通过sample_flag来过滤通过采样超时线程是什么意思获取的卡顿异常。通过此方式获取的堆栈,大概率为卡顿场景,可以更加有针对性的去分析和解决。

  1. 卡死监控优化

开源众包比卡顿,卡死的误报大多发生在后台(目前Heimdallr提供后台卡死过滤,如果对后台卡死不关心的业务方可以自行打开)。安全教育平台因为后台场景的限制,当前App的线程优先级更低,而且随时存在被系统挂起的可能,这给我们进行卡死时间的判定带来安全生产法了很多问题。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

上面的Case描述的是一个卡死的误报场景,因为在后台的原因线程的优先级较低,因此1、2、3任务执行的时间要比前台更久,更加容易超过线程数我们的卡死阈值。而后,因为iOS系统的策略问题,后台应用被挂起(suspend),直至某一个时间点因为内存紧张,将整个应用杀死线程是什么意思。但请注意,这个流程属于App正常的生命周期范畴,并不是WatchDog。而按照我们之前的策略,这将会被判定为卡死。由于我们无法监听到susp线程的几种状态end事件,所以这种场景目appreciate前还无法排除误报。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

还有一种误触发卡死的case是,suspend发appreciate生在8s阈值前,在长时间的挂起后,应用被resume,此时8s的超时被触发。但是实际上,我们appointment的App只有在8s中的很少一部分时间在ruapproachnning线程是什么意思,大部分时间都是被挂起,所以不应该触发卡安全死判定。归根结底开源阅读是卡死线程数计时的准确性问题。

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

为了解决上安全生产法面的问题,对计时策略进行了改进。相比于直接进行8s的等待,我们将时间细分为8个1s。如果在这段时间内App被挂起,等到恢复时也不会直接超过8s的阈值,而仅仅会造成最多1s的误差。\

此外,上面也提到过,卡死有的时候可能是线程池的七个参数多个耗时场景累计导致的。为了能够跟踪主线程的变化,在抓栈之后的采样阶段,对主线程进行堆栈采样,并将其一起上报。结合采样中获取的主线程堆栈,我们可以得到一个主线程开源矿工堆栈变化的时间线,能够更加准确的帮助定位问题所在。(时间线功能在Heimdallr 0.7.15之后支持)

字节跳动 iOS Heimdallr 卡死卡顿监控方案与优化之路

最后,我们发现部线程池的七个参数分卡死场景是由于OC Runtime Loc开源阅读k导致的(大概率是dyldOC Runtime LoAPPck造成的死锁)。一旦发生这种类型的卡死,其它所有线程的OC代码都会因此而阻塞,当然也包括监听线程,卡死监控此时就无法捕获这个异常。为了能够覆线程数越多越好吗盖所有场景,我们把卡死、卡顿模块的所有逻辑进行了C/C++重构,解除了对OC调用的依赖,并且性能相比与OC实现进一步得到提升。

结语

HeimdallrANRWatchDog模块经过一段时间的迭代与优化,达到了一个全面、稳定、可靠的状态。这期间的一些优化思路借鉴了一些开源矿工安全教育的APM框架,并结合使用方的实际需求进行不断改开源阅读进。感谢所有使用方的反馈,帮助我们不断完善我们的功能与体验。后续我们会继续针对Watchappstoredog场景增加防卡死功能,帮助接入方能够在无侵入式的情况下,解决通用场景的卡死approach问题。


火山引擎 APMPl开源代码网站githubus 应用性能监控是火山引擎应用开发套件 MARS 下的性能监控产品。我们通过先进的数据采集与监控技术,为线程是什么意思企业提供全链路的应用性能监控服务,助力企业提升异常问题排查与解决的效率。目前我appstore们面向中小企apple苹果官网业特别推出「APMPlus 应用性能监控企业助力行动」,为中小企业提供应线程的几种状态用性能监控免费资源包。现在申请,有机会获得60天免费性能监控服务,最高可享6000万条事件量。

点击这里,立线程是什么意思即申请