Android 15 新 API:内存追踪利器 ProfilingManager

前言

我们都知道 Android Studio 里内置了 Profiler tool 供大家对 App 在 Memory、CPU、Network、Power 等角度进行 dump 和分析。

但如果一个内存相关的 bug 是运行时发生的,而且很难复现,那么后期就很难准确定位发生时的具体状况。

值得兴奋的是 Android 15 将直面这个痛点:引入了 ProfilingManager API,允许 app 对 Memory 进行动态的、随时随地的 dump。

生成的文件默认存在本地,也可以通过网络传递到 offboard,方便开发者事后回溯。

API 说明

ProfilingManager 主要提供了 3 个方法。

registerForAllProfilingResults

注册 profiling 请求的回调和执行的线程,需要如下两个参数:

ParametersDescriptions
executorExecutor: 回调执行的线程池实例,不可为空
listenerConsumer: 携带 profiling 结果的 listener 实例,不可为空

unregisterForAllProfilingResults

注销 profiling 请求的回调,如果没有指定 listener 参数的话,将移除所有 callback。

ParametersDescriptions
listenerConsumer: 待移除的回调,null 的话移除所有

requestProfiling

请求进行一次 profiling 操作,有非常详细的参数可供设置:

ParametersDescriptions
profilingTypeint: profiling 操作的类型,主要包括 dump Java 堆的 PROFILING_TYPE_JAVA_HEAP_DUMP,dump 堆的 PROFILING_TYPE_HEAP_PROFILE, dump 栈的 PROFILING_TYPE_STACK_SAMPLING 和 dump 系统 trace 的PROFILING_TYPE_SYSTEM_TRACE参数不能为空
parametersBundle: 携带请求额外的相关参数, 如果包含了未定义的参数类型,请求会失败,在 callback 当中以 ERROR_FAILED_INVALID_REQUEST 结果进行返回,参数可为空。
tagString: 回来识别 dump 输出的 tag 标签,其中的前 20 个字符将会以小写的形式拼接到 dump 文件名中,参数可为空
cancellationSignalCancellationSignal: 支持请求侧用来取消 dump 的 cancellation 实例,如果 dump 结果已出来的话,会被返回。参数可为空,此时将执行系统默认的超时时间,之后结束 dump。
executorExecutor: 回调执行的线程池实例,参数可为空。但如果没有其他 executor 注册的话,该请求会被无视。
listenerConsumer: 监听操作结果的实例,registerForAllProfilingResults() 注册的 callback 同样也会被回调,参数可为空。但如果没有其他 listener 注册的话,该请求会被无视。

需要说明的是

  • 很多时候,并不推荐直接使用该 API 进行 dump,相反可以采用 androidx 中封装好的高层级接口进行请求。该接口内部会依据可用选项和简化的参数进行正确地请求。
  • 并非所有情况都会得到响应
  • 需要同时考虑 result 的监听和执行它的线程池两个参数,要么都设置,要么都不设置交给 registerForAllProfilingResults() 一起设置

ProfilingResult

在上述提到的 registerForAllProfilingResults() 里会回调 ProfilingResult 参数过来,它用来封装单次请求 profiling 操作的结果。

主要提供了这几个方法来获得信息:

  • getErrorCode():获取 profiling 请求失败的原因,如果成功的话,值为 ERROR_NONE 即 0,其他的还有 ERROR_FAILED_RATE_LIMIT_SYSTEM 等值
  • getErrorMessage():获取额外的失败信息
  • getTag():请求时传入的参数 tag,方便回溯
  • getResultFilePath():获取 profiling 结果文件的路径

实战

留意一下,需要将 Android 15 的 SDK 升级到 revision 3 才可以看到该 API。

     class ProfilingActivity : AppCompatActivity() {
         private val singleThreadExecutor = Executors.newSingleThreadExecutor()
     ​
         private val profilingResultConsumer = Consumer<ProfilingResult> {
             Log.d(TAG_PROFILING, "accept profilingResult:${it.printProfilingResult()}")
         }
     ​
         private val profilingManager by lazy {
             getSystemService(ProfilingManager::class.java)
         }
     ​
         override fun onCreate(savedInstanceState: Bundle?) {
             ...
             binding.dump.setOnClickListener {
                 Log.d(TAG_PROFILING, "button dump tapped")
     ​
                 profilingManager.registerForAllProfilingResults(
                     singleThreadExecutor,
                     profilingResultConsumer
                 )
             }
     ​
             binding.request.setOnClickListener {
                 Log.d(TAG_PROFILING, "button request tapped")
     ​
                 profilingManager.requestProfiling(
                     // ProfilingManager.PROFILING_TYPE_SYSTEM_TRACE,
                     // ProfilingManager.PROFILING_TYPE_JAVA_HEAP_DUMP,
                     // ProfilingManager.PROFILING_TYPE_STACK_SAMPLING,
                     ProfilingManager.PROFILING_TYPE_HEAP_PROFILE,
                     null,
                     "TEST_FOR_PROFILING_MANAGER",
                     null,
                     singleThreadExecutor,
                     profilingResultConsumer
                 )
             }
     ​
             binding.stop.setOnClickListener {
                 Log.d(TAG_PROFILING, "button stop tapped")
     ​
                 profilingManager.unregisterForAllProfilingResults(profilingResultConsumer)
             }
         }
     }

可以看到我们在代码里设置的 tag 为 “TEST_FOR_PROFILING_MANAGER”

在这里插入图片描述

我们点击 “register dump profile” button 开始注册回调,然后点击 “request dump profile” button 开始请求。

看下 Profiling 的 log 输出。

点击完 request 之后需要等待一段时间(系统默认的 dump 超时为 120s 左右)才会看到 dump 结果。

注意,不要重复点击,否则会收到如下错误的 callback。其中 3 对应的是 ERROR_FAILED_PROFILING_IN_PROGRESS,表示仍在 dump 中,该重复请求被拒绝。

ProfilingResult{errorCode:3 errorMessage:null resultFilePath:null tag:TEST_FOR_PROFILING_MANAGER}

下面我们以如下 4 种 dump 类型看下具体的 ProfilingResult 输出内容。

PROFILING_TYPE_JAVA_HEAP_DUMP

04-21 19:37:32.220  7184  7270 D Profiling: accept profilingResult:ProfilingResult{errorCode:0 errorMessage:null resultFilePath:/data/user/0/com.ellison.osvdemo/files/profiling/profile_testforprofilingmana_2024-04-21-19-37-26.perfetto-java-heap-dump tag:TEST_FOR_PROFILING_MANAGER}

可以看到成功输出了 Java heap 的 dump 文件,并且咱们的 tag 被拼接到了文件名中,而且将_删除并限制了 20 的长度。

所以咱们设置的 tag 最好不要包含字母以外的字符,并且不要过长,不然不方便定位 tag。

PROFILING_TYPE_HEAP_PROFILE

04-21 19:47:16.810  7474  7552 D Profiling: accept profilingResult:ProfilingResult{errorCode:0 errorMessage:null resultFilePath:/data/user/0/com.ellison.osvdemo/files/profiling/profile_testforprofilingmana_2024-04-21-19-45-11.perfetto-heap-profile tag:TEST_FOR_PROFILING_MANAGER}

和上面的 Java dump 一样,成功输出了 heap 全量的 dump 文件。

PROFILING_TYPE_STACK_SAMPLING

04-21 19:53:01.043  7704  7790 D Profiling: accept profilingResult:ProfilingResult{errorCode:0 errorMessage:null resultFilePath:/data/user/0/com.ellison.osvdemo/files/profiling/profile_testforprofilingmana_2024-04-21-19-51-55.perfetto-stack-sample tag:TEST_FOR_PROFILING_MANAGER}

dump stack 的记录也是一样,不再赘述。

PROFILING_TYPE_SYSTEM_TRACE

04-21 15:43:33.926  4730  4775 D Profiling: accept profilingResult:ProfilingResult{errorCode:7 errorMessage:Trace is not supported until redaction lands resultFilePath:null tag:null}

和前面 3 中 type 不同,这种 dump 系统 trace 的请求总是会直接失败。

ProfilingResult 结果对应的 errorCode 为 7,常量名称为 ERROR_FAILED_INVALID_REQUEST,表示请求失败了:这是一个不合法的 ProfilingRequest。

The request failed due to invalid ProfilingRequest.

单从这个 error 定义来看,压根不知道问题出在哪。

在 API 章节里我们提到过,如果调用 requestProfiling() 时传递的 Bundle 参数包含了不支持的 key-value,会造成 ERROR_FAILED_INVALID_REQUEST 错误。

但可以看到:实际上咱们的 DEMO 代码里啥 bundle 都没携带,所以应该不是这个原因。

好在,ProfilingRequest 结果还打携带了 errorMessage,其内容为:Trace is not supported until redaction lands

笔者尝试依据该 message 找到蛛丝马迹,但无论在 Android 官网,还是在 Android 源码里,抑或是在 AOSP issue 的首页上,都没找到合相关的记录。

我猜测是 PROFILING_TYPE_SYSTEM_TRACE 需要某个 DOC 里没说明的 Bundle 参数,造成了失败。当然也有可能是 beta 版阶段的系统 bug。

后续再看。

perfetto 支持

以 PROFILING_TYPE_JAVA_HEAP_DUMP 的文件为例,从 data 目录里 pull 之后,在 “https://link.zhihu.com/?target=https%3A//ui.perfetto.dev/”) 中打开,可以进行分析。

)
在这里插入图片描述

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AB 实验是一种常用的实证研究方法,用于评估因果关系和确定特定干预措施对于所关注变量的影响。科学归因则是指通过合理的分析与推断,确定事件发生的原因或因果关系。《科学归因与增长的利器》是一本以AB 实验为基础的电子书籍,主要介绍了如何利用AB 实验在增长领域中取得成功。 该书首先介绍了AB 实验的基本概念和原则。AB 实验通常包括两个或多个实验组,其中一个组作为对照组,其他组则接受某种干预措施。通过与对照组的比较,可以得出干预措施对于所关注变量的影响。这一方法在科学研究中已被广泛使用,例如医学研究中的药物试验,市场营销中的广告测试等。 接着,该书介绍了科学归因在增长领域的应用。增长是指通过运用各种策略和技术,提高企业的业务指标,如用户数量、销售额等。通过AB 实验可以确定不同的增长策略对于业务指标的影响效果,并进一步优化策略,提升增长效果。科学归因可以帮助、决策者判断哪些策略或因素对于增长效果贡献最大,以及如何合理分配资源来实现最好的增长效果。 最后,该书还提供了实际案例和技巧,帮助读者学习如何设计和执行AB 实验,以及如何进行科学归因分析。通过深入了解AB 实验和科学归因的方法,读者可以更好地应用于实际工作中,提升增长策略的效果。 总而言之,《科学归因与增长的利器》是一本以AB 实验为基础,介绍了如何应用科学归因分析在增长领域取得成功的电子书。通过理解和应用书中的方法和技巧,读者可以更好地评估和优化增长策略,提升业务指标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值