抖音 Android 性能优化系列:新一代全能型性能分析工具 Rhea

由于这个阶段采集的只有 Java 方法层的数据,在抖音启动 IO 耗时优化工作中,Method Trace 无法提供哪些函数进行了 IO 操作,以及 IO 操作读取/写入了哪些文件,给优化工作带来了较大的难度。另外在一些复杂场景中,Method Trace 只记录函数执行时长,但是不能准确定位是由于多线程同步等锁或者系统 IO 导致的执行时间变长。

针对上面的问题,我们意识到一套优秀的 Trace 工具还需要融合更多的系统事件,于是工具进入了第三阶段的打磨。

第三阶段:动态一体化 Trace 工具规划


Rhea 1.0 和 2.0 在抖音早期的性能优化工作中成绩显著,但随着优化工作的深入同时也暴漏诸多局限与不便。

一方面,使用常规的 Systrace 工具做性能优化,本身有诸多局限性。一是 Trace 信息少,在默认情况下,只包含系统预置的耗时打点信息,并不足以支持常规的耗时分析需要在 App 侧手动调用  Trace.beginSection 和 Trace.endSection  方法才能获取更多函数耗时信息,为避免影响线上包大小,使用完以后又需手动移除,一上一下事倍而功半。二是 Systrace 本身性能损耗大,特别是应用通过插桩的方式对业务代码进行大量的打点时,极端情况性能损耗会超过 50%。三是 Systrace 完全依赖 PC 端工具抓取,不够灵活。尤其是需要能够稳定复现性能问题的场景,对于一些特定区域或者特定用户群体才能复现的问题无法获直接高效的取到有效信息,依赖研发或者测试走查,甚至用户反馈的部分概率问题即使走查也无法通过 Systrace 获取到对应的信息,从而导致优化效率低。

另一方面,通过简单定制 Trace 的获取函数耗时相较于 Systrace,虽然有显著的性能提升,和更高的灵活性,但数据只包含基本的耗时信息,在部分复杂场景(如持有锁引起的耗时),数据仍存在局限。

如上工具都均已无法完全满足抖音的启动、首刷以及低端机等核心场景的性能优化工作,我们需要重新设计和规划功能更加强大的动态一体化 Trace 工具来辅助分析性能。

  1. 该工具要非常灵活,可以不依赖 PC 端的抓取脚本,同时支持线上线下,能够在应用任何想要抓取数据的时候运行,作为一个平台性工具,Rhea 还需要支持动态扩展,支持多种场景的配置和动态开关,可以将任意需要的信息进行采集。

  2. 该工具抓取的 Trace 信息要全面,能够采集和追踪包括 ATrace 插桩、等锁信息、I/O 信息以及 Binder 耗时等在内的多种信息。

  3. 要支持可视化,统一的格式进行输出和格式化,最终以兼容 Systrace 的结果进行前端展示和使用,尽量不要改变使用者习惯。

  4. 性能损耗要低,以免带偏性能优化方向。

因此,我们重新设计了新一代 Trace 分析工具:

整体上,App 通过集成 Rhea SDK 在打包时不限层级插入函数耗时桩方法,在运行时插入 IO、Binder、Lock 等相关 Trace 信息,支持动态配置,统一 Trace 格式为 atrace,同时支持获取系统级别的 Linux ftrace、Android Framework atrace 和 App 插入的 atrace 信息,能够不依赖 PC 抓取,最终提供可视化显示。具体实现如下:

一、不依赖 PC 抓取 Trace

为了实现不依赖 PC 抓取 Trace,我们有必要先了解下 Android atrace 的实现机制。首先,是 atrace 包括的数据源包括:

其中,用户空间的数据包括了应用层的自定义 Trace、系统层的 gfx 渲染相关 Trace、系统层打的锁相关的 Trace 信息等,其最终都是通过调用 Android SDK 提供的Trace.beginSection或者 ATRACE_BEGIN 记录到同一个文件点/sys/kernel/debug/tracing/trace_marker 中的。此节点允许用户层写入字符串,ftrace 会记录该写入操作时的时间戳,当用户在上层调用不同函数时,写入不同的调用信息,比如函数进入和退出分别写入,那么 ftrace 就可以记录跟踪函数的运行时间。atrace 在处理用户层的多种 trace 类别时,只是激活不同的 TAG,如选择了 Graphics,则激活 ATRACE_TAG_GRAPHICS,将渲染事件记录到 trace_marker。

而内核空间的数据主要是一些补充的分析数据 freq、sched、binder 等,常用的比如 CPU 调度的相关信息包括:

  • CPU 频率变化情况

  • 任务执行情况

  • 大小核的调度情况

  • CPU Boost 调度情况

这些信息是 App 可以通过直接读取/sys/devices/system/cpu 节点下相关信息获得,而另外一部分标识线程状态的信息则只能通过系统或者 adb 才能获取,且这些信息不是统一的一个节点控制,其需要激活各自对应的事件节点,让 ftrace 记录下不同事件的 tracepoint。内核在运行时,根据节点的使能状态,会往 ftrace 缓冲中打点记录事件。例如,激活线程调度状态信息记录,需要激活类似如下相关节点:

events/sched/sched_switch/enable

events/sched/sched_wakeup/enable

激活后,则可以获取到线程调度状态相关的信息,比如:

  • Running: 线程在正常执行代码逻辑

  • Runnable: 可执行状态,等待调度,如果长时间调度不到,说明 CPU 繁忙

  • Sleeping: 休眠,一般是在等待事件驱动

  • Uninterruptible Sleep: 不可中断的休眠,需要看 Args 的描述来确定当时的状态

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值