带你读《2022技术人的百宝黑皮书》——APM 页面加载耗时校准(1)https://developer.aliyun.com/article/1340943?groupCode=taobaotech
业务埋点带来了标准的不统一
每一个页面的实现都是不一样的,每一个业务方对自己的可视终点有不一样的定义。有的人认为页面第一张图片出来了就是可视,有些人认为页面数据请求回来了就是可视,有些人认为第一帧上屏就是可视,一千个人心中有一千个哈姆雷特,这也导致埋出来的数据往往千差万别,甚至会出现肉眼看见更慢的页面数据更好的情况。
框架复杂,在现有基础上改动成本有些过高
当前淘宝首页会有 N 多个模版,并且模版间还存在组合关系。淘宝首页是根据模版下发进行渲染数据,如果说对模版改造有些不太现实。同时,现阶段的淘宝,业界中能见到的跨端框架,在淘宝都能看到影子,让所有框架改造一个统一的可视标准,让所有业务方手动打入可视时间有一些不切实际。
业务与框架侧都不具有全局视角,导致埋点不准确
往往业务方将数据请求回来交给容器渲染时就认为可视了,可却忽略了容器处理数据需要时间,数据上屏需要时间,容器将图片 URL 交给图片库进行加载亦需要时间。对于业务方而言,上诉耗时,对他是透明并不感知的,对于框架而言,只是进行一次渲染,并不知是页面加载还是刷新页面。
基于上诉问题,我们将解决方案放在业务无入侵、统一可视终点标准上,并最终提出了 8060 算法。
可视算法初步实现
8060 可视算法规则很简单,主要是将屏幕范围内的 View,对 X、Y 轴进行投影,当覆盖 X 轴长度的 80%、Y 轴的 60% 就认为是可视。
为了将可视计算性能进一步提升,我们决定异步计算可视终点。
异步计算可视是 APM 中比较巧妙的实现,因为可视算法涉及到 UI,Android 开发同学都知道,对 UI 的操作不是必须在主线程中实现,只需要保证操作的线程和 UI 的创建线程保持一致即可,那么 Activity 界面的 UI 正常情况下都是在主线程创建的,这是否意味着可视算法只能在主线程中执行呢?答案显然是不一定。其实 Android 系统需要保证的是 UI 的状态,通过对线程的保护,可以很好的保证 UI 状态的一致性。
如果多线程对 UI 进行写操作,那么会导致 UI 的状态被破坏;但是如果是多线程读操作呢,多线程读 UI 的状态并不会破坏 UI 的状态,只会导致一个问题,即在读的过程中读到一个不稳定的状态,导致程序异常,比如说 NPE, APM 在尝试异步 UI 可视算法的起初,就遇到了 NPE 的一些问题。不过这到不是一个很严重的问题,因为当你读到了一个不稳定的状态时,恰恰说明 UI 的状态还不稳定,意味着 UI 在变化。抛弃本次计算,重新开始计算,直到有一次完整的页面计算。这个算法其实来源于读写锁的设计思路,如果读不会导致数据变化,那么在 UI 线程在读操作的时候异步线程也可以同时的读 UI,并不会对 UI 的状态导致破坏,程序依旧能正常运行。异步线程只需要保护好自己的运行状态,能正确处理一些异常即可。
带你读《2022技术人的百宝黑皮书》——APM 页面加载耗时校准(3)https://developer.aliyun.com/article/1340941?groupCode=taobaotech