Time Profile原理
如果要反应CPU使用情况,第一反应是记录每个方法执行时间。然后根据调用堆栈把每个方法执行的时间累加起来,呈现给使用者来反应CPU使用情况。Time Profile并没有事无巨细的记录每个方法的执行时间,而是使用了定时采样方式来反应CPU使用情况。
每隔1ms,Time Profile会记录一下当前执行堆栈,就像Xcode中断点调试那样的堆栈。如果1s内CPU都在忙碌,Time Profile会截取到1000个堆栈,这1s中的Detail pane中的Call Tree就根据堆栈的调用结构组织起来的,所以Time Profile Call Tree和调用堆栈看起来很像,实际上Time Profile Call Tree等于每个时间点调用堆栈的叠加
如果把Time Line拉到足够大,还能看到样本标记,可以在Detail pane中选中sample来看采集到的样本
在分析CPU图谱,有两个很重要的概念,weight 和 self weight
weight & self weight.jpg
weight:指定时间,此方法在采样堆栈出现的次数。eg:weight 46ms,就是这段时间里,此方法被采样46次
self weight:指定时间,此方法处于堆栈最后面的次数。eg1:self weight 1ms,就是这段时间里,采样时,此方法在调用堆栈最后面1次;eg2:self weight 0ms,就是这段时间里,采样时此方法一次也没有在调用堆栈最后面,也就是这个方法并没有干实事,全是调用其他方法做事的
实操
先使用instrument捕捉CPU使用情况,然后
- 在time line上选出想要分析的片段
- 选中想要分析的线程,分析卡顿就选中主线程,楼主一般都是分析主线程
- 沿着占用CPU高的方法,一级一级展开call tree,分析调用
分析:
可以看到使用CPU最多的是CA::Context::commit_transaction(CA:Transaction*),这是系统渲染的方法,所以可以知道,是由于需要渲染的东西太多了,导致的卡顿(不知道这个是系统渲染的方法也没关系,继续往call tree找就能看出来)。
继续沿着CPU使用率高的方法往下找,能看到这样的情况
占用CPU高的方法
不知道CA::Context::commit_transaction(CA:Transaction*)的,从这里就可以看出,是UILabel渲染占了很多CPU
找到这里就算交差了吗?是渲染耗时多所以就没办法解决了吗?
本着科学认真(杠精)的态度,我决定尝试分析这些渲染是不是有水分(有没有不必要渲染、重复渲染)
我的页面有很多UILable,首先我需要知道这些UILabel的渲染占比。我采取的方法是,继续往下找,找到我可以控制的方法为止,像下面
找到可以控制方法
然后重写UILable,给每个UILabel起个标志性的名字,覆盖drawTextInRect方法,这样在instrument里就能区分各个UILabel的渲染耗时占比了
区分UILabel的耗时占比
上面的图并不是同一个CPU使用片段,只是用来示意如何区分不同UILabel的渲染。
到这里,可以找出是不是有不必要渲染。比如某个label是隐藏状态,但是占了渲染耗时,这是不必要的
至于重复渲染和更多的排除不必要渲染方法,等我想到再更。
作者水平有限,如有错误,还请不吝赐教
网友评论