[iOS] 线上UI卡顿监控与符号化速度优化

本文参考以下文章,做了一点优化,提升了卡顿监测的准确性,性能,符号化速度等等。
iOS实时卡顿监控深入理解RunLoopiOS版微信界面卡顿监测方案深入剖析 iOS 性能优化BSBacktraceLogger

UI卡顿检测

通过监测主runloop循环次数来判断是否发送卡顿。

什么是runloop?
runloop就是线程里的一个循环,退出该循环的条件是程序结束,程序什么时候结束自己定,类似MFC中消息循环。

为什么要有runloop?
线程保活,事件分发,线程频繁创建销毁耗资源,不希望线程频繁创建销毁。

怎么监控主runloop循环次数?
runloop循环的过程中会抛通知出来,在异步线程中创建一个runloop观察者监听这些通知即可。

怎么检测UI发生了卡顿?
监控主runloop循环次数,流畅情况下,一般循环60次,对应60帧。
假设认为掉了10帧,人眼能明显感受到卡顿,10 * 16.67 ms 约 166 ms,那么runloop超过166ms没回调通知给我的观察者,判定为卡顿,并且要“非常非常及时”获取下主线程的调用栈,栈顶的方法就是发生卡顿的方法。

看下图:这是网友根据runloop源码画的流程图

起一个线程用信号量卡着,每166ms执行一次,用个变量last记录最后一次runloop抛出来通知,如果发生166ms超时,去看 last 是什么值,如果是 kCFRunLoopBeforeSources 和 kCFRunLoopAfterWaiting,表示自己的代码发生卡顿,因为这两个通知后面处理的是 source0系统代码,source1用户代码,timer代码事件。发生了卡顿就在监控线程将其调用栈获取下来。

另外页面切换速度,FPS帧率,都跟主循环正相关,因为viewDidLoad等等事件都在主线程执行,UI也在主线程绘制。监测了主runloop,这两个指标其实可以不用在监测。

符号化

符号化就是给一个内存地址 0x00001234 找到其符号 -[ViewController viewDidLoad] 的过程,因为mach-o文件中包含了LC_SYMTAB段,该段中包含符号表。
注意,iOS系统做了优化,系统库的符号不在内存中,会提示 <redacted>

符号化参考BSBacktraceLogger所写

改进的地方有:
1.预处理所有image,记录下image中所需要的各个segment基址,image内存地址范围等等,避免每次用个for循环来查找segment基址,预处理后查找基址从 O(N) 降到 O(1),注意点:image可以动态加载,动态删除,好在iOS中不会删除,只会在APP启动时会逐渐加载,加完后image数量不会变化,如果image数量有变,那么得重新预处理一次。

2.查找一个内存地址 address 在哪一个 image 内,返回该 image 索引
由于有预处理image地址范围,并对地址排了序,qsort()排序,并且image地址不重叠,那么这里查找一个image直接用二分查找,从原来的两个for循环的O(n^2)降到了O(log n),为什么不用哈希查找是因为地址空间太大,64位下有2^64个地址,大约 16777216T,太大了存不下。

3.加缓存,缓存 (address, symbol) 地址到symbol符号结构体的二元组
使用自己实现的LRU缓存,比NSCache快4倍,文章地址:https://www.jianshu.com/p/1f8e36285539

4.监控线程只获取调用栈,另起一个线程进行符号化,相当于监控线程是生产者,其他线程是消费者,一对一生产消费模型。

优化结果:1000次符号化调用
7个栈:
优化后:50ms,,,优化前:1800ms

70个栈:
优化后:800ms,,,优化前:11800ms

那么除以1000就是一次符号化的时间,大约是 0.05ms 到 0.8ms 之间能获取到全部调用栈,提高了准确性。因为在50ms发生了卡顿,该卡顿可能在51ms消失,调用栈变化十分快,必须要在最短时间内捕捉到调用栈,才能准确,如果要在几毫秒后才捕捉到,那可能就不是发生卡顿的调用栈了,导致结果不准。

优化后的代码暂时未贴出,以后会考虑开源的。

线上UI卡顿监控结果

UI卡顿监控SDK终于上线了,灰度范围5万个用户,线上 0 崩溃。
后台已捕捉到几千处方法卡顿和卡顿调用栈(卡顿定义:UI线程超过500ms没响应判定为卡顿)
卡顿主要原因是:有代码在主线程同步请求网络,主线程读写数据库,写文件,加锁,做数据解析,数据计算等等。
修复完这些卡顿,APP流畅性将得到提升,用户体验提升。

监控SDK本身的性能消耗:(iPhone 6s, iOS 9.2 测得)
SDK启动时间:0.05 ms
SDK启动后:CPU 接近 0%,内存大约几十kb
包体积:72 kb
磁盘使用:3 kb,(一次启动数据上报流量 2 kb)
常驻线程:启动一分钟内有3个,收集完数据后,常驻线程仅1个,CPU 接近 0%

另外我还一个业务型的SDK在月活1.1亿的APP上,崩溃数只有11个。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259