触摸事件,手势,界面更新都会触发runloop,因为注册了observer(???)
界面卡顿是由哪些原因导致的?
死锁:主线程拿到锁 A,需要获得锁 B,而同时某个子线程拿了锁 B,需要锁 A,这样相互等待就死锁了。
抢锁:主线程需要访问 DB,而此时某个子线程往 DB 插入大量数据。通常抢锁的体验是偶尔卡一阵子,过会就恢复了。
主线程大量 IO:主线程为了方便直接写入大量数据,会导致界面卡顿。
主线程大量计算:算法不合理,导致主线程某个函数占用大量 CPU。
大量的 UI 绘制:复杂的 UI、图文混排等,带来大量的 UI 绘制。
针对这些原因,我们可以怎么定位问题呢?
死锁一般会伴随 crash,可以通过 crash report 来分析。
抢锁不好办,将锁等待时间打出来用处不大,我们还需要知道是谁占了锁。
大量 IO 可以在函数开始结束打点,将占用时间打到日志中。
大量计算同理可以将耗时打到日志中。
大量 UI 绘制一般是必现,还好办;如果是偶现的话,想加日志点都没地方,因为是慢在系统函数里面。
具体到卡顿检测,有几个问题需要仔细处理:
怎么知道主线程发生了卡顿?
子线程以什么样的策略和频率来检测主线程?这个是要发布到现网的,如果处理不好,带来明显的性能损耗(尤其是电量),就不能接受了。
堆栈上报了上来怎么分类?直接用 crash report 的分类不适合。
卡顿 dump 下来的堆栈会有多频繁?数据量会有多大?
全量上报还是抽样上报?怎么在问题跟进与节省流量直接平衡?