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

2024-08-31 14:12

本文主要是介绍Android 15 新 API:内存追踪利器 ProfilingManager,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

android15-base-profiling.png

本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!

前言

我们都知道 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 之后,在 ui.perfetto.dev 中打开,可以进行分析。

转存失败,建议直接上传图片文件

DEMO 源码

AndroidOSVDemo

结语

ProfilingManager API 允许 App 直接进行各种 Memory 数据的 dump,相信这能在一定程度上帮助开发者进行内存相关问题的回溯,不再像以前那样被动。

从上面的实战也能看到目前部分功能还存在些问题,期待正式版本能够修复。

感兴趣的朋友可以在 Android 15 稳定版的时候再行体验。

笔者猜测因为 Memory 是最高优的关注点,所以目前 ProfilingManager 只支持 dump Memory。但我相信随着该 API 的成熟和普及,以及确实有 dump 其他点强劲需求的话,肯定会逐步支持更多 dump 的内容。

参考资料

  • ProfilingManager
  • ProfilingResult

这篇关于Android 15 新 API:内存追踪利器 ProfilingManager的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1124126

相关文章

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

2025最新版Android Studio安装及组件配置教程(SDK、JDK、Gradle)

《2025最新版AndroidStudio安装及组件配置教程(SDK、JDK、Gradle)》:本文主要介绍2025最新版AndroidStudio安装及组件配置(SDK、JDK、Gradle... 目录原生 android 简介Android Studio必备组件一、Android Studio安装二、A

Java JAR 启动内存参数配置指南(从基础设置到性能优化)

《JavaJAR启动内存参数配置指南(从基础设置到性能优化)》在启动Java可执行JAR文件时,合理配置JVM内存参数是保障应用稳定性和性能的关键,本文将系统讲解如何通过命令行参数、环境变量等方式... 目录一、核心内存参数详解1.1 堆内存配置1.2 元空间配置(MetASPace)1.3 线程栈配置1.

Python内存管理机制之垃圾回收与引用计数操作全过程

《Python内存管理机制之垃圾回收与引用计数操作全过程》SQLAlchemy是Python中最流行的ORM(对象关系映射)框架之一,它提供了高效且灵活的数据库操作方式,本文将介绍如何使用SQLAlc... 目录安装核心概念连接数据库定义数据模型创建数据库表基本CRUD操作创建数据读取数据更新数据删除数据查

Redis高性能Key-Value存储与缓存利器常见解决方案

《Redis高性能Key-Value存储与缓存利器常见解决方案》Redis是高性能内存Key-Value存储系统,支持丰富数据类型与持久化方案(RDB/AOF),本文给大家介绍Redis高性能Key-... 目录Redis:高性能Key-Value存储与缓存利器什么是Redis?为什么选择Redis?Red

使用Go调用第三方API的方法详解

《使用Go调用第三方API的方法详解》在现代应用开发中,调用第三方API是非常常见的场景,比如获取天气预报、翻译文本、发送短信等,Go作为一门高效并发的编程语言,拥有强大的标准库和丰富的第三方库,可以... 目录引言一、准备工作二、案例1:调用天气查询 API1. 注册并获取 API Key2. 代码实现3

k8s容器放开锁内存限制问题

《k8s容器放开锁内存限制问题》nccl-test容器运行mpirun时因NCCL_BUFFSIZE过大导致OOM,需通过修改docker服务配置文件,将LimitMEMLOCK设为infinity并... 目录问题问题确认放开容器max locked memory限制总结参考:https://Access

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动