本讲是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间,总共执行了多少次内存分配(有的可能已经释放) |