缘起是看到网易云音乐技术团队发布的一篇《systrace 统计方法耗时》的文章,文章讲解了如何通过 hook 的方式将 trace 开关打开,并实现不依赖 PC 开启 Trace 功能,实现线上抓取。文章思路与流程非常清晰,是一个不错的实践(造轮子)机会,我将此文转发给正在研究 xcrash 和 xhook 的同事,我俩一拍即合,打算利用这个机会撸一个框架,并且,同事还给我发了一篇更全面的实践文章《抖音 Android 性能优化系列:新一代全能型性能分析工具 Rhea》。
我们非常建议,在阅读这款框架源码的时候,一定要看下上述提到的两篇文章。
为什么我们也想做一个:
插桩方法未正确闭合:
目前 Trace 工具更多的还是在线下使用,由于插桩过多影响了包大小,使得我们线上部分只能对小规模的用户群体定向打开,没法全量上线定位线上大规模用户的性能问题
由于放置在 github 的源码没有对外发布依赖,故这里就介绍下如何使用,我相信,如果有同学对这方面有兴趣的话,这一定难不倒他(主要是我们太懒了,笑哭)。
由于 github 项目使用的是复合构建引入的插件模块,如果想接入到自己项目的话,可以参考 setting.gradle,通过 includebuild 来引入插件模块。
在 app 模块的 build.gradle 中使用 tracePlugin 插件:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'tracePlugin'
}
trace {
pkg = "com.bomber.strace"
ignoreClass = [
"com.bomber.strace.*.bean.*",
"com.bomber.*.R",
"com.bomber.*.R\\\$.*",
"com.bomber.*.BuildConfig",
]
}
在 Application 中对其进行初始化:
class LancerApp : Application() {
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
installLancer()
}
private fun installLancer() {
val traceDir = filesDir.absolutePath + File.separator + "trace"
val r = Lancer.getInstance().initialize(
Build.VERSION.SDK_INT,
traceDir,
BuildConfig.DEBUG
)
Log.d("TraceApp", "r = $r")
}
}
initialize 方法需要传入三个参数:
在需要记录 trace 日志和关闭 trace 日志的地方进行记录:
Lancer.getInstance().start()
Lancer.getInstance().stop()
示例 demo 中演示的是从 application 的 attachBaseContext 就开启 start 日志记录,对于想记录业务模块的话,可自由搭配记录位置。
运行 demo 时,需要在 local.properties 下配置下 ndk 路径,如:
ndk.dir=/Users/mac/Library/Android/sdk/ndk/25.1.8937393
release 包效果:
perfetto 效果:
[1]
perfetto ui : https://ui.perfetto.dev/