本讲是Android Camera性能分析专题的第48讲,我们介绍Perfetto内存分析之使用Perfetto来分析Java Heap。
更多资源:
资源 | 描述 |
---|---|
在线课程 | 极客笔记在线课程 |
知识星球 | 星球名称:深入浅出Android Camera 星球ID: 17296815 |
极客笔记圈 |
如何查看某个进程的Java Heap用量
对App开发者而言,可以使用Android Studio的Profiler功能。但最快捷的方式还是使用dumpsys,可以执行:
dumpsys meminfo [pid/pkg]
举例:dumpsys meminfo org.codeaurora.snapcam
输出如下:
图中的Java Heap是如下2项的和
- Dalvik Heap(ART申请的Buffer)
- .art mmap(ART map的buffer)
通过dumpsys meminfo我们能知道某个进程Java Heap的总大小,但这还不够,留下2个疑问:
- dumpsys meminfo显示的是总的Java Heap用量,如何breakdown?
- 如何知道申请的这8692KB java heap在代码中的callstack?
这就引出了下面两个Perfetto相关的主题
- Java Heap Dumps
- Java Heap Sampling
Java Heap Dumps – 对Java Heap进行Breakdown
Java Heap Dumps概述
Java Heap Dumps保留所有Java对象间的引用(retained)关系(非callstack),也就是GC不掉的对象,通过火焰图将这些对象呈现出来。
这里的引用定义为:ObjectX对象通过成员变量Z 引用 N Bytes的ObjectY对象
一般来说,一个对象可以通过多条路径访问,Java Heap Dumps只显示最短路径。
更具体的Java Heap Dumps保留的是下图Obj1/Obj2/Obj3 不可回收的部分:
Java Heap Dumps 配置文件说明
常用的配置如下,这里是对高通Camera App进行dump,dump的时间间隔为500ms
data_sources: {
config {
name: "android.java_hprof"
target_buffer: 0
java_hprof_config {
process_cmdline: "org.codeaurora.snapcam"
continuous_dump_config {
dump_phase_ms: 5
dump_interval_ms: 500
}
}
}
}
能配置的字段说明如下:
Field | Description |
---|---|
process_cmdline | 字符串类型,要抓取的命令行白名单列表,与 /proc/ |
pid | Uint64类型,要抓取的pid白名单列表,例如: pid: 5858 pid: 5599 |
target_installed_by | Android12上支持,字符串类型,指定允许profile的分区 |
min_anonymous_memory_kb | Uint32类型,不profile (anon RSS + swap < given value) 小于指定大小的进程 |
dump_smaps | Bool类型,是否dump smaps(/proc/self/smaps.) |
ignored_types | 字符串类型,从profile中排出不感兴趣的对象,比如” sun.misc.Cleaner” |
ContinuousDumpConfig如下:
Field | Description |
---|---|
dump_phase_ms | Uint32类型,在第一个连续dump之前等待的毫秒数。 |
dump_interval_ms | Uint32类型,相邻两次dump的时间间隔 |
scan_pids_only_on_start | Bool类型 如果为True,则扫描所有进程以查找 process_cmdline,并仅在数据源启动时按 min_anonymous_memory_kb 进行过滤。(Android S及以下默认值) 如果为False,则重新扫描所有进程以在每次dump时查找。(Android T及以上默认值) |
从Perfetto分析Java Heap Dumps
如下图所示,dump完后通过Perfetto UI打开,就能看到这23.17MB不能被回收的Java Heap分别是由哪些部分组成:
其中,
Tab | 描述 |
---|---|
Size | 某对象通过此路径到GC Root 引用了多少字节。 |
Objects | 某对象通过此路径到GC Root 引用了多少对象。 |
Java Heap Sampling – Java Heap分配时的调用栈
Java Heap Sampling介绍
- 通过采样方式,记录对象分配/创建时的callstacks,不包含对象释放/被GC回收的callstacks
-
Heapprofd通过Hook heap buffer的申请函数来完成heap分配采样(libc.malloc heap是hook C语言的malloc/free和C++的operator new/delete ),java 使用的com.android.art heap。
-
给定一个n字节的采样间隔,平均每分配n字节就会对一个分配进行采样。默认的采样率是4096字节。
Java Heap Sampling配置
- 运行tools/heap_profile命令时加上–heaps com.android.art (命令行方式)
- 在HeapprofdConfig中加入
heaps: "com.android.art"
(Perfetto方式)
data_sources: {
config {
name: "android.heapprofd"
target_buffer: 0
heapprofd_config {
sampling_interval_bytes: 4096
process_cmdline: "org.codeaurora.snapcam"
heaps: "com.android.art"
continuous_dump_config {
dump_phase_ms: 5
dump_interval_ms: 500
}
block_client: false
}
}
}
从Perfetto分析Java Heap Sampling
Tab | 描述 |
---|---|
Total allocation Size | 从开始dump到本次dump间,总共分配了多少内存(有的可能已经释放) |
Total allocation count | 从开始dump到本次dump间,总共执行了多少次内存分配(有的可能已经释放) |