首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Matrix-iOS 卡顿监控

Matrix-iOS 卡顿监控

作者头像
微信终端开发团队
发布于 2019-05-16 07:51:25
发布于 2019-05-16 07:51:25
13.4K1
举报

前言


在早期开发 iOS 微信的过程中,我们时不时会收到类似的反馈:

  • “我的微信卡在主界面,怎么也滑动不了”
  • “我的微信从后台切换前台卡了一下,最近偶尔会遇到几次”,等等。

这类问题有个共同点:用户的微信在一段时间内无法点击;即使获得用户的操作路径,也无法重现。

我们把这类问题叫做卡顿问题。这类问题很影响用户的体验,是必须进行解决的。为了精确地定位用户的卡顿问题,iOS 微信在 2014 年 9 月份上线了卡顿监控系统。在这几年间,卡顿监控经历了几次优化,不断成熟,在这里我们将其分享出来。

什么是卡顿


卡顿就是在应用使用过程中出现界面不响应或者界面渲染粘滞的情况。而应用界面的渲染以及事件响应是在主线程完成的,出现卡顿的原因可以归结为主线程阻塞。

在开发过程中,遇到的造成主线程阻塞的原因可能是:

  • 主线程在进行大量I/O操作:为了方便代码编写,直接在主线程去写入大量数据;
  • 主线程在进行大量计算:代码编写不合理,主线程进行复杂计算;
  • 大量UI绘制:界面过于复杂,UI绘制需要大量时间;
  • 主线程在等锁:主线程需要获得锁A,但是当前某个子线程持有这个锁A,导致主线程不得不等待子线程完成任务。

针对这些问题,如果我们能够捕获得到卡顿当时应用的主线程堆栈,那么问题就迎刃而解了。有了堆栈,就可以知道主线程在什么函数哪一行代码卡住了,是在等什么锁,还是在进行I/O操作,或者是进行复杂计算。有了堆栈,就可以对问题进行针对性解决。

原理


在 iOS/macOS 平台应用中,主线程有一个 Runloop。Runloop 是一个 Event Loop 模型,让线程可以处于接收消息、处理事件、进入等待而不马上退出。在进入事件的前后,Runloop 会向注册的 Observer 通知相应的事件。

Runloop 的详细介绍可以网上查阅《深入理解RunLoop》。一个简易的 Runloop 流程如下所示:

Matrix 卡顿监控在 Runloop 的起始最开始和结束最末尾位置添加 Observer,从而获得主线程的开始和结束状态。卡顿监控起一个子线程定时检查主线程的状态,当主线程的状态运行超过一定阈值则认为主线程卡顿,从而标记为一个卡顿。

目前微信使用的卡顿监控,主程序 Runloop 超时的阈值是 2 秒,子线程的检查周期是 1 秒。每隔 1 秒,子线程检查主线程的运行状态;如果检查到主线程 Runloop 运行超过 2 秒则认为是卡顿,并获得当前的线程快照。

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

退火算法

为了降低检测带来的性能损耗,我们为检测线程增加了退火算法:

  • 每次子线程检查到主线程卡顿,会先获得主线程的堆栈并保存到内存中(不会直接去获得线程快照保存到文件中);
  • 将获得的主线程堆栈与上次卡顿获得的主线程堆栈进行比对:
    • 如果堆栈不同,则获得当前的线程快照并写入文件中;
    • 如果相同则会跳过,并按照斐波那契数列将检查时间递增直到没有遇到卡顿或者主线程卡顿堆栈不一样。

这样,可以避免同一个卡顿写入多个文件的情况;避免检测线程遇到主线程卡死的情况下,不断写线程快照文件。

耗时堆栈提取


子线程检测到主线程 Runloop 时,会获得当前的线程快照当做卡顿文件。但是这个当前的主线程堆栈不一定是最耗时的堆栈,不一定是导致主线程超时的主要原因。

例如,主线程在绘制一个微信logo,过程如下:

子线程在检测到超出阈值时获得的线程快照,主线程的当前任务是“画小气泡”。但其实“画大气泡”才是耗时操作,导致主线程超时的主要原因。Matrix 卡顿监控通过主线程耗时堆栈提取来解决这个问题。

卡顿监控定时获取主线程堆栈,并将堆栈保存到内存的一个循环队列中。如下图,每间隔时间 t 获得一个堆栈,然后将堆栈保存到一个最大个数为 3 的循环队列中。有一个游标不断的指向最近的堆栈。

微信的策略是每隔 50 毫秒获取一次主线程堆栈,保存最近 20 个主线程堆栈。这个会增加 3% 的 CPU 占用,内存占用可以忽略不计。

当主线程检测到卡顿时,通过对保存到循坏队列中的堆栈进行回溯,获取最近最耗时堆栈。

如下图,检测到卡顿时,内存的循环队列中记录了最近的20个主线程堆栈,需要从中找出最近最耗时的堆栈。Matrix 卡顿监控用如下特征找出最近最耗时堆栈:

  • 以栈顶函数为特征,认为栈顶函数相同的即整个堆栈是相同的;
  • 取堆栈的间隔是相同的,堆栈的重复次数近似作为堆栈的调用耗时,重复越多,耗时越多;
  • 重复次数相同的堆栈可能很有多个,取最近的一个最耗时堆栈。

获得的最近最耗时堆栈会附带到卡顿文件中。

卡死卡顿


Matrix 中内置了应用被杀原因的检测机制。这个机制从 Facebook 的博文 中获得灵感,在其基础上增加了系统强杀的判定。Matrix 检测应用被杀原因的具体机制如下图所示:

Matrix 检测到应用卡死被强杀,会把应用上次存活时的最后一份卡顿日志标记为卡死卡顿。

性能数据


Matrix 卡顿监控不打开耗时堆栈提取,性能损耗可以忽略不计。

打开耗时堆栈提取后,性能损耗和定时获取主线程堆栈的间隔有关。实测,每隔 50 毫秒不断获取主线程堆栈,会增加 3% 的 CPU 占用。

结尾


以上是 iOS 微信卡顿监控的原理性介绍,它同样可以应用在 macOS 平台上。iOS 微信团队通过卡顿监控上报的堆栈,找到微信的代码不合理之处或者是一些性能瓶颈,通过卡顿监控的辅助,尽可能地提升 iOS 微信的流畅性,给用户带来更加极致美好的体验。

卡顿监控依然在不断进行优化,不断地扩展能力,近期我们计划会为它增添捕获应用的耗电堆栈等,使其功能更加完备。我们决定通过 Matrix 将其开源,并希望能获得大家的意见和建议。

开源地址

[Matrix]https://github.com/Tencent/matrix/tree/master/matrix/matrix-apple

请给 Matrix 一个 Star !

欢迎提出你的 issue 和 PR。

var first_sceen__time = (+new Date());if ("" == 1 && document.getElementById('js_content')) { document.getElementById('js_content').addEventListener("selectstart",function(e){ e.preventDefault(); }); } (function(){ if (navigator.userAgent.indexOf("WindowsWechat") != -1){ var link = document.createElement('link'); var head = document.getElementsByTagName('head')[0]; link.rel = 'stylesheet'; link.type = 'text/css'; link.href = "//res.wx.qq.com/mmbizwap/zh_CN/htmledition/style/page/appmsg_new/winwx45ba31.css"; head.appendChild(link); } })();

陈志炯

赞赏

长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

阅读原文

阅读

分享 在看

已同步到看一看

取消 发送

我知道了

朋友会在“发现-看一看”看到你“在看”的内容

确定

已同步到看一看写下你的想法

最多200字,当前共字 发送

已发送

朋友将在看一看看到

确定

写下你的想法...

取消

发布到看一看

确定

最多200字,当前共字

发送中

微信扫一扫 关注该公众号

微信扫一扫 使用小程序

即将打开""小程序

取消 打开

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WeMobileDev 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
matrix源码里监控runloop,为啥要添加那么多observer?
matrix源码里监控runloop,为啥要添加那么多observer?
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
iOS 卡顿监测方案总结
最近在写 APM 相关的东西,所以整理了一下 iOS 中卡顿监测的那些方案,不了解卡顿的原理的可以看这篇文章iOS 保持界面流畅的技巧[1],写的很好。
网罗开发
2021/11/02
2.3K0
微信iOS卡顿监控系统
引子 微信 iOS 团队在值班的时候,时不时会收到这样的卡顿反馈:“用户A 刚才碰到从后台切换前台卡了一下,最近偶尔会遇到几次”、“用户B 反馈点对话框卡了五六秒”、“现网有用户反馈切换 tab 很卡”。 这些反馈有几个特点,导致跟进困难: 不易重现。可能是特定用户的手机上才有问题,由于种种原因这个手机不能拿来调试;也有可能是特定的时机才会出问题,过后就不能重现了(例如线程抢锁)。 操作路径长,日志无法准确打点 对于这些界面卡顿反馈,通常我们拿用户日志作用不大,增加日志点也用处不大。只能不断重试希望能够重
微信终端开发团队
2018/01/29
5.5K0
微信iOS卡顿监控系统
Matrix-iOS 耗电监控
前言 在微信开发过程中,有时会收到一些反馈说,手机使用微信一段时间后就开始发烫了。为了跟进用户的发烫问题,最开始的时候,我们只能通过日志看看用户在这段时间做了些什么操作,努力去复现问题。 会导致手机发烫的原因很多,有可能只是用户在阳光下使用手机;但也有可能真的是微信某个模块代码有问题,导致当前 CPU 占用过高。这很让人头疼。如果能像查卡顿问题一样,有堆栈就好了。 在 WWDC 2018  What’s New in Energy Debugging,苹果推介了 Energy Log 这种日志来查耗电问题
微信终端开发团队
2019/08/09
4.2K0
Matrix-iOS 耗电监控
Matrix for iOS/macOS 正式开源了
Matrix for iOS/macOS 是一款微信团队研发并日常使用的性能探针工具,目前集成在 iOS 和 macOS 微信的 APM(Application Performance Manage)平台中使用。Matrix for iOS/macOS 建立了一套 iOS 和 macOS 平台上统一的应用性能接入框架,通过对性能监控项的异常数据进行采集,帮助开发者开发出更高质量的应用,从而提升应用的用户体验。 Matrix for iOS/macOS 的各个插件已经在微信内部稳定运行了几年,现在作为 Ma
微信终端开发团队
2019/05/16
3.7K0
Matrix for iOS/macOS 正式开源了
【开源公告】Matrix for iOS/macOS 正式开源了
Matrix for iOS/macOS 是一款微信团队研发并日常使用的性能探针工具,目前集成在iOS和macOS微信的APM(Application Performance Manage)平台中使用。
腾讯开源
2019/05/16
1.9K0
【开源公告】Matrix for iOS/macOS 正式开源了
RunLoop总结:RunLoop的应用场景(四)App卡顿监测
今天要介绍的RunLoop使用场景很有意思,在做长期项目,需要跟踪解决用户问题非常有用。 使用RunLoop 监测主线程的卡顿,并将卡顿时的线程堆栈信息保存下来,下次上传到服务器。
Haley_Wong
2018/08/22
1.3K0
《广研Android卡顿监控系统》
实现背景 应用的使用流畅度,是衡量用户体验的重要标准之一。Android 由于机型配置和系统的不同,项目复杂App场景丰富,代码多人参与迭代历史较久,代码可能会存在很多UI线程耗时的操作,实际测试时候也会偶尔发现某些业务场景发生卡顿的现象,用户也经常反馈和投诉App使用遇到卡顿。因此,我们越来越关注和提升用户体验的流畅度问题。 已有方案 在这之前,我们将反馈的常见卡顿场景,或测试过程中常见的测试场景使用UI自动化来重复操作,用adb系统工具观察App的卡顿数据情况,试图重现场景来定位问题。 常用的方式是使用
腾讯Bugly
2018/03/23
4.7K2
微信Android客户端的卡顿监控方案
文章开始,先聊一聊卡顿与ANR的关系:产生卡顿的根本原因是UI线程不能够及时的进行渲染,导致UI的反馈不能按照用户的预期,连续、一致的呈现。产生卡顿的原因多种多样,很难一一列举,而ANR是Google人为规定的概念,产生ANR的原因最多也只有四个。 一方面,两者息息相关,事实上,长时间的UI卡顿是导致ANR最常见的原因;但另一方面,从原理上来看,两者既不充分也不必要,是两个维度的概念。 而市面上的一些卡顿监控工具,经常被拿来监控ANR(卡顿阈值设置为5秒),这其实很不严谨:首先,5秒只是发生ANR的其中一
微信终端开发团队
2021/07/14
3.9K0
iOS卡顿监控方案浅析
最近,小编一直致力于解决一项性能问题,那就是iOS输入法输入卡顿问题的监控,通过一段时间的调研,小编整理出来了一些监控方法,这里就分享给大家,希望可以给正在进行这方面工作的测试同学一点帮助。
用户5521279
2020/05/27
1.6K0
移动端性能监控方案Hertz
性能问题是造成App用户流失的罪魁祸首之一。App的性能问题包括崩溃、网络请求错误或超时、响应速度慢、列表滚动卡顿、流量大、耗电等等。而导致App性能低下的原因有很多,除去设备硬件和软件的外部因素,其中大部分是开发者错误地使用线程、锁、系统函数、编程范式、数据结构等导致的。即便是最有经验的程序员,也很难在开发时就能避免所有导致性能低下的“坑”,因此解决性能问题的关键是在于能不能尽早地发现和定位这些“坑”。 美团外卖在实践中通过总结常见性能问题,并在学习了业内微信、360等性能监控技术原理后,开发了一套移动端
美团技术团队
2018/03/12
2.9K0
移动端性能监控方案Hertz
Android卡顿监控系统
Android 由于机型配置和系统的不同,项目复杂App场景丰富,代码多人参与迭代历史较久等,实际测试时候也会偶尔发现某些业务场景发生卡顿的现象...
likunhuang
2018/07/03
7.9K3
Android卡顿监控系统
探秘redis持久化流程
| 导语 本文详细分析redis持久化的俩种模式的详细流程 一. 概述redis持久化的俩种模式 随着redis越来越流行,使用者不在仅仅满足其只是一个内存数据库,同时也期望其能将内存数据落磁盘,这样重启服务就不会导致缓存数据丢失了 redis持久化有俩种模式模式,分别如下: 二. rdb持久化模式 1.rdb持久化核心思路 获取当前内存快照并将快照数据保存到磁盘实现当前数据全量备份 2.rdb持久化难点 (1)如何获取当前内存数据快照 redis利用linux fork子进程后( cow机制:htt
腾讯Bugly
2019/05/16
8340
探秘redis持久化流程
Android卡顿优化 | 自动化卡顿检测方案与优化(AndroidPerformanceMonitor / BlockCanary)
当然,我们可以在logcat中定位关键词blockInfo, 看到同样的详细的信息:
凌川江雪
2020/04/09
2.7K0
Android卡顿优化 | 自动化卡顿检测方案与优化(AndroidPerformanceMonitor / BlockCanary)
iOS 知识点回顾(三)
温故而知新 目录 一. GCD和OperationQueue 二. CADisplayLink、NSTimer使用注意 三. 内存布局 四. Tagged Pointer 五. copy和mutableCopy 六. OC对象的内存管理 七. AutoreleasePool自动释放池 八. 图片的解压缩到渲染过程 九. 应用卡顿的原因以及优化 十. APP的启动 一. GCD和NSOperationQueue GCD 可用于多核的并行运算; GCD 会自动利用更多的 CPU
且行且珍惜_iOS
2020/01/15
8120
手写解析微信Matrix性能监控日志的工具
在精读了Matrix的源码之后,我发出了赞叹和吐槽两种声音。值得赞扬的是,「这个APM框架的设计思路确实鬼斧神工,有很多值得Android开发者学习的地方,深入了解它,能够扩宽我们的编程视野。」 令人吐槽的就是,「从文档的丰富性,代码的可读性,代码的注释量,开源的一条龙服务等方面讲,他们做的还不太好。」 作为国内的顶尖开发团队,这些方面与国外的顶尖开源开发团队还是有不小的差距。
音视频开发进阶
2021/06/09
2.5K1
手写解析微信Matrix性能监控日志的工具
克魔助手 - iOS性能检测平台
众所周知,如今的用户变得越来越关心app的体验,开发者必须关注应用性能所带来的用户流失问题。目前危害较大的性能问题主要有:闪退、卡顿、发热、耗电快、网络劫持等,但是做过iOS开发的人都知道,在开发过程中我们没有一个很直观的工具可以实时的知道开发者写出来的代码会不会造成性能问题,虽然Xcode里提供了耗电量检测、内存泄漏检测等工具,但是这些工具使用效果并不理想(如Leak无法发现循环引用造成的内存泄漏)。所以这篇文章主要是介绍一款实时监控app各项性能指标的工具,包括CPU占用率、内存使用量、内存泄漏、FPS、卡顿检测,并且会分析造成这些性能问题的原因。
爱学iOS的小麦子
2024/02/02
3700
Matrix-iOS 内存监控
FOOM(Foreground Out Of Memory),是指App在前台因消耗内存过多引起系统强杀。对用户而言,表现跟crash一样。Facebook早在2015年8月提出FOOM检测办法,大致原理是排除各种情况后,剩余的情况是FOOM,具体链接:https://code.facebook.com/posts/1146930688654547/reducing-fooms-in-the-facebook-ios-app/。
微信终端开发团队
2019/05/16
8.1K0
微视iOS SIGKILL BUG实例
微视iOS接入QAPM作为项目的性能监控工具已有一年多,打开的功能包括掉帧率、卡顿、SIGKILL、内存触顶、VC泄露和大块内存监控。在QAPM同学的日常运营过程中,发现微视的Tapd在近期某段时间内突然出现有较多的sigkill类型的bug上报,于是借这次案例对sigkill进行一次分析总结。
硬骨见小鹿
2019/03/22
10.4K0
微视iOS SIGKILL BUG实例
iOS 之如何利用 RunLoop 原理去监控卡顿?
1. 前言 卡顿问题,就是在主线程上无法响应用户交互的问题。如果一个 App 时不时地就给你卡一下,有 时还长时间无响应,这时你还愿意继续用它吗?所以说,卡顿问题对 App 的伤害是巨大的,也是 我们
网罗开发
2021/05/14
3K0
iOS 之如何利用 RunLoop 原理去监控卡顿?
QQ 9“傻快傻快”的?!带你看看背后的技术秘密
最新发布的 QQ 9 自上线以来,流畅度方面收获了众多用户好评,不少用户戏称 QQ 9 “傻快傻快”的,快到“有点不习惯了都”。
腾讯云开发者
2024/04/24
2.3K2
QQ 9“傻快傻快”的?!带你看看背后的技术秘密
相关推荐
iOS 卡顿监测方案总结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档