抖音Android岗面试性能优化篇之Rhea(新一代全能型性能分析工具)【速看】

本文详细介绍了抖音Android团队开发的Rhea,这是一个新一代全能型性能分析工具,旨在解决传统工具在性能优化中的局限性。Rhea经历了三个阶段的演进,从基于Systrace的补充到高性能全场景的Trace抓取,再到动态一体化Trace工具的规划。文章涵盖了Rhea的优势、架构演进、最佳实践以及未来规划,展示了其在解决Android性能问题上的强大能力,尤其在锁耗时、IO耗时和Binder耗时等方面的改进,适用于移动开发和性能优化的面试准备。
摘要由CSDN通过智能技术生成

写在前面的话

性能优化这个知识点是很多大厂面试中都会问到的问题,尤其是想要面试抖音的Android岗的朋友。

用户交互响应的耗时,作为 Android 用户日常感知最深的一项性能指标,在日常开发中有着非常重要的意义。而抖音 Android 基础技术团队为打造极致的交互响应体验,一直在致力于极致性能的探索,其中就包括如何打造极致的耗时检测工具。

今天要和大家分享的是抖音内部人员的技术总结。正在准备抖音Android岗面试的朋友记得点赞收藏哦,希望本文对大家的学习和工作有帮助。

原文地址:新一代全能型性能分析工具 Rhea

推荐阅读:重磅首发!昨晚最新爆出的“移动开发性能优化笔记”,GitHub已标星8K,看完我爱了!

概述

俗话说,工欲善其事,必先利其器,我们要做好性能优化,首要是要能够发现性能的问题,这就需要有靠谱的工具来帮助我们做性能分析。市面上主流的性能分析工具有:Systrace、TraceView、Android Studio 的 CPU Profiler。相信做性能优化的同学对这些工具应该都是非常熟悉了,抖音最早也是用 Systrace 作为主要的分析工具,在优化前期也发挥了比较大的作用。

随着抖音的性能优化来到了深水区,我们需要发现并解决更细粒度、更多维度的性能问题,我们会关注几毫秒的耗时,关注线上一些低端机用户遇到的锁阻塞和 IO 等待问题。而市面上这些主流的性能分析工具因其使用的局限性和较大的性能损耗,已经无法满足抖音性能优化的需求。为了能够百尺竿头更进一步,我们需要开发更加灵活、精细化以及多元的信息和工具来辅助我们进行高效的优化工作。

在这样的背景之下,抖音 Android 基础技术团队开发了 Rhea( [ˈriːə] 瑞亚,寓意时光女神)跟踪器(Tracer),其是一种通过静态代码插桩技术自动添加 Trace,用来分析 APP 运行时耗时的性能分析工具,意思是要做一个功能全面、追求效率、大家都喜欢的女神,也符合我们工具的核心设计原则。Rhea 跟踪器获取 Trace 不仅要性能损耗低,还要能脱离 PC 端工具在 App 侧直接抓取,跟踪更多常规函数耗时的同时还要可以跟踪系统调用,如:锁信息、I/O 耗时、Binder IPC 以及更多其他信息。最后,还提供转换脚本工具,用于将原始跟踪文件生成可视化报告,便于用户分析性能问题。

优势对比

Rhea 当前因其无侵入、高性能、信息全等优势已在字节多个 APP 上落地使用,效果明显,已多次帮助大家快速发现性能问题,其包含的信息包括不限层级的应用层函数、IO、锁、Binder、CPU 调度等耗时信息等,其部分效果如下所示:

相对于其他 Android 性能排查工具,其具体优势表现为:

当前,Systrace 只能监控特定系统信息,监控应用层的耗时则需要手动打点;TraceView 性能跟采样率关系密切,采样过于频繁性能开销巨大,采样过低又难以精准发现问题函数;Nanoscope 虽然几乎没有性能损耗,但每次都需定制 ROM 刷机,使用成本非常高,并且这些工具都只支持 debugable 的应用程序线下分析,这些工具在针对 APP 性能优化都有不甚完美之处,而 Rhea 是一个集大成者,融合了各工具优势并弥补了相关缺陷。

架构演进之路

第一阶段:基于 Systrace 补充函数耗时 Trace

Systrace 是 Android 性能调试优化的常用工具,它可以收集进程的活动信息,如函数调用耗时、锁等;也可以收集内核信息,如 CPU 调度、IO 活动、Binder 调用信息等;这些信息会统一时间轴,在 Chrome 浏览器中显示出来,方便工程师性能调试、优化卡顿等工作。因此,抖音早期性能优化首选 Systrace 作为主要工具,其大致流程如下:

1. 功能改造

Systrace 工具只能监控特定系统调用的耗时情况,它不支持应用程序代码的耗时分析,所以在使用时有一些局限性。原生 Systrace 需要开发者在方法的起止位置手动加入 Trace.beginSectionTrace.endSection 方法对,这个过程就变成了开发者预判耗时位置,然后在手动加入监控函数对,通过不断重复添加监控点、打包、运行、采集数据,从而一步步完成耗时方法定位,这也使得 Systrace 的使用成本变得极高。

为了提高 Systrace 的易用性,我们开发了 Rhea 1.0 对 Systrace 功能进行了改造,加入了自动插桩机制:通过字节码插桩自动完成 Trace.beginSectionTrace.endSection 方法对的插入,并且通过运行时限制方法层级的方式,来有效控制因引入监控带来的性能损耗。

  • 插桩类及桩方法伪代码:
class Tracer{
    method_stack = list()
    max_size = 6
 
    methodIn(method_id, method_name){
        if(method_stack.size()<=max_size){
            method_stack.push(method_id)
            Trace.beginSection(method_name)
        }
    }
 
    methodOut(){
        if(method_stack.size>0){
            method_stack.pop()
            Trace.end()
        }
    }
}
  • 被插桩方法:
method1(){
    Tracer.methodIn(1,method1)
     ...
    Tracer.methodOut()
}

输出数据如下所示,指定层级内所有方法即可按照预期展示在输出 html 中:

2. 方法 Did not finished 问题

在使用改造后的 systrace 时,我们时常会遇到如下问题:

分析发现,主要原因在于方法在运行期执行中被中断,例如:方法执行过程中发生异常后,被其调用者方法捕获,发生异常方法的 Systracer.o 方法未被调用。如图:test 方法中的 error 方法执行时出现 arr[2]的数组越界,导致 test 方法中的插桩方法 SysTracer.o(13L)未调用,异常被 onCreate 中的 catch 块捕获,从而导致 test 的插桩方法没有被成对调用,最终导致了 test 外层所有的方法调用都无法正确闭合。(注意:本小结提到的桩方法,即 SysTracer 相关方法,均是通过字节码插桩自动插入

解决办法,在外层所有异常捕获的位置,额外插入桩方法,重新这种异常调用链下的桩方法不成对问题。如下图:

3. 依然存在的问题

  • 性能问题

随着 Rhea 1.0 功能的深入使用,在带来极大便利的同时,功能本身的不足也逐渐暴露出来。在采集数据过程中,其本身的性能损耗会导致在一些实际性能优化过程中会带偏方向。经我们严格测试,其性能损耗有 11.5%左右,如下所示:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值