系统UI开发规范&技巧 — 内存篇
每个 Android 应用程序在运行时都会被分配一个独立的进程,每个进程有自己的虚拟地址空间。SystemUI作为高优常驻进程,高效地分配和管理设备的内存资源,是确保SystemUI流畅运行的关键。
内存相关简介
Meminfo
Android meminfo 字段详解https://developer.android.com/topic/performance/memory-overview?hl=zh-cnhttps://developer.android.com/tools/dumpsys?hl=zh-tw
dumpsys meminfo 命令用于获取 Android 设备上进程的内存信息。以下是 dumpsys meminfo 命令输出中每个信息的含义:
adb shell dumpsys meminfo com.android.systemui
Applications Memory Usage (in Kilobytes):
Uptime: 95803295 Realtime: 99507806
** MEMINFO in pid 4786 [com.android.systemui] **
Pss Private Private SwapPss Rss Heap Heap Heap
Total Dirty Clean Dirty Total Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------
Native Heap 110314 110272 0 5629 118392 146568 117524 23973
Dalvik Heap 49021 48956 0 32 57504 133014 34710 98304
Dalvik Other 12309 9888 0 28 16180
Stack 4708 4708 0 308 4716
Ashmem 2393 2372 0 0 5328
Other dev 263 4 252 0 908
.so mmap 3904 220 272 68 73000
.jar mmap 2590 0 164 0 59396
.apk mmap 60625 16 53356 12 82568
.ttf mmap 3654 0 680 0 28028
.dex mmap 786 0 708 4 1996
.oat mmap 319 0 0 0 16868
.art mmap 1313 992 124 0 23432
Other mmap 1653 4 68 0 5148
EGL mtrack 5456 5456 0 0 5456
GL mtrack 34504 34504 0 0 34504
Unknown 33610 31820 1788 908 34964
TOTAL 334411 249212 57412 6989 568388 279582 152234 122277
App Summary
Pss(KB) Rss(KB)
------ ------
Java Heap: 50072 80936
Native Heap: 110272 118392
Code: 55436 266716
Stack: 4708 4716
Graphics: 39960 39960
Private Other: 46176
System: 27787
Unknown: 57668
TOTAL PSS: 334411 TOTAL RSS: 568388 TOTAL SWAP PSS: 6989
Objects
Views: 2433 ViewRootImpl: 12
AppContexts: 73 Activities: 0
Assets: 53 AssetManagers: 0
Local Binders: 969 Proxy Binders: 335
Parcel memory: 149 Parcel count: 257
Death Recipients: 36 WebViews: 0
Native Allocations
Count Total(kB)
------ ------
Other (malloced): 8327 795
Other (nonmalloced): 1468 823
Bitmap (malloced): 206 18771
Bitmap (nonmalloced): 18 2998
SQL
MEMORY_USED: 757
PAGECACHE_OVERFLOW: 333 MALLOC_SIZE: 53
DATABASES
pgsz dbsz Lookaside(b) cache hits cache misses cache size Dbname
PER CONNECTION STATS
4 24 44 103 110 4 /data/user_de/0/com.android.systemui/databases/notification.db
4 8 0 0 0 (attached) temp
4 24 46 37 30 4 /data/user_de/0/com.android.systemui/databases/notification.db (1)
4 20 41 3 19 4 /data/user_de/0/com.miui.aod/databases/onetrack_cache
4 24 43 4 20 5 /data/user_de/0/com.miui.aod/databases/universal_ot_monitor_db
4 20 41 13 28 4 /data/user_de/0/com.android.systemui/databases/onetrack_cache
4 20 41 3 28 4 /data/user_de/0/com.android.systemui/databases/onetrack_cache
4 188 32 114 32 5 :memory:
POOL STATS
cache hits cache misses cache size Dbname
140 144 284 /data/user_de/0/com.android.systemui/databases/notification.db
3 20 23 /data/user_de/0/com.miui.aod/databases/onetrack_cache
4 21 25 /data/user_de/0/com.miui.aod/databases/universal_ot_monitor_db
13 29 42 /data/user_de/0/com.android.systemui/databases/onetrack_cache
3 29 32 /data/user_de/0/com.android.systemui/databases/onetrack_cache
114 33 147 :memory:
纵轴:
横轴:
App Summary:
Gfxinfo
adb shell dumpsys gfxinfo com.android.systemui
关键信息
//frameworks/base/libs/hwui/renderthread/CacheManager.cpp
CacheManager::dumpMemoryUsage
......
Pipeline=Skia (Vulkan)
Memory policy:
Max surface area: 3548160
Max resource usage: 510.94MB (x144)
Background retention: 50% (altUiHidden = true)
IsSystemOrPersistent
GPU Context timeout: 10
Contexts: 12 (stopped = 6)
CPU Caches:
Glyph Cache: 4.99 MB (1 entry)
Glyph Count: 334
Total CPU memory usage:
5228710 bytes, 4.99 MB (0.00 bytes is purgeable)
GPU Caches:
Other:
Other: 207.56 KB (1 entry)
Image:
Surface: 231.20 KB (2 entries)
Scratch:
Surface: 7.35 MB (9 entries)
GrVkTextureRenderTarget: 83.40 MB (37 entries)
Buffer Object: 254.12 KB (76 entries)
GrVkImage: 0.00 bytes (48 entries)
Total GPU memory usage:
95867448 bytes, 91.43 MB (112.19 KB is purgeable)
......
GraphicBufferAllocator buffers:
Handle | Size | W (Stride) x H | Layers | Format | Usage | Requestor
0xb400007241ed1890 | 61.50 KiB | 320 ( 384) x 41 | 1 | 1 | 0x10000300 | passBlur-24893
0xb400007241ed19f0 | 820.00 KiB | 1280 (1280) x 164 | 1 | 1 | 0x b00 | VRI[DynamicIslandWindow]#10(BLAST Consumer)10
0xb400007241ed74b0 | 1039.50 KiB | 320 ( 384) x 693 | 1 | 1 | 0x10000300 | passBlur-24893
0xb400007241ed87f0 | 13860.00 KiB | 1280 (1280) x 2772 | 1 | 1 | 0x b00 | VRI[NotificationShade]#11(BLAST Consumer)11
0xb400007241ed92f0 | 1039.50 KiB | 320 ( 384) x 693 | 1 | 1 | 0x10000300 | passBlur-24893
0xb400007241edccb0 | 1039.50 KiB | 320 ( 384) x 693 | 1 | 1 | 0x10000300 | passBlur-24893
0xb400007241edd7b0 | 61.50 KiB | 320 ( 384) x 41 | 1 | 1 | 0x10000300 | passBlur-24893
0xb400007241ede990 | 13860.00 KiB | 1280 (1280) x 2772 | 1 | 1 | 0x b00 | VRI[NotificationShade]#11(BLAST Consumer)11
0xb400007241ee0250 | 61.50 KiB | 320 ( 384) x 41 | 1 | 1 | 0x10000300 | passBlur-24893
0xb400007241ee0510 | 13860.00 KiB | 1280 (1280) x 2772 | 1 | 1 | 0x b00 | VRI[NotificationShade]#11(BLAST Consumer)11
0xb400007241ee1170 | 13860.00 KiB | 1280 (1280) x 2772 | 1 | 1 | 0x b00 | VRI[NotificationShade]#11(BLAST Consumer)11
0xb400007241ee1430 | 13860.00 KiB | 1280 (1280) x 2772 | 1 | 1 | 0x b00 | VRI[NotificationShade]#11(BLAST Consumer)11
0xb400007241ee1c70 | 820.00 KiB | 1280 (1280) x 164 | 1 | 1 | 0x b00 | VRI[DynamicIslandWindow]#10(BLAST Consumer)10
0xb400007241f0a570 | 22.75 KiB | 448 ( 448) x 13 | 1 | 1 | 0x b00 | VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9
0xb400007241f0b5f0 | 820.00 KiB | 1280 (1280) x 164 | 1 | 1 | 0x b00 | VRI[DynamicIslandWindow]#10(BLAST Consumer)10
0xb400007241f11370 | 820.00 KiB | 1280 (1280) x 164 | 1 | 1 | 0x b00 | VRI[DynamicIslandWindow]#10(BLAST Consumer)10
0xb400007241f4a310 | 22.75 KiB | 448 ( 448) x 13 | 1 | 1 | 0x b00 | VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9
0xb400007241f501f0 | 22.75 KiB | 448 ( 448) x 13 | 1 | 1 | 0x b00 | VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9
0xb400007241f50770 | 22.75 KiB | 448 ( 448) x 13 | 1 | 1 | 0x b00 | VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9
0xb400007241f67ab0 | 22.75 KiB | 448 ( 448) x 13 | 1 | 1 | 0x b00 | VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9
0xb400007241f6b5d0 | 820.00 KiB | 1280 (1280) x 164 | 1 | 1 | 0x b00 | VRI[DynamicIslandWindow]#10(BLAST Consumer)10
0xb400007241f73450 | 260.00 KiB | 1280 (1280) x 52 | 1 | 1 | 0x b00 | VRI[NavigationBar0]#0(BLAST Consumer)0
0xb400007241f735b0 | 260.00 KiB | 1280 (1280) x 52 | 1 | 1 | 0x b00 | VRI[NavigationBar0]#0(BLAST Consumer)0
0xb400007241f73710 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar]#1(BLAST Consumer)1
0xb400007241f73c90 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar]#1(BLAST Consumer)1
0xb400007241f73f50 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar]#1(BLAST Consumer)1
0xb400007241f74a50 | 260.00 KiB | 1280 (1280) x 52 | 1 | 1 | 0x b00 | VRI[NavigationBar0]#0(BLAST Consumer)0
0xb400007241f75550 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar]#1(BLAST Consumer)1
0xb400007241f756b0 | 260.00 KiB | 1280 (1280) x 52 | 1 | 1 | 0x b00 | VRI[NavigationBar0]#0(BLAST Consumer)0
0xb400007241f76730 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar]#1(BLAST Consumer)1
0xb400007241f774f0 | 260.00 KiB | 1280 (1280) x 52 | 1 | 1 | 0x b00 | VRI[NavigationBar0]#0(BLAST Consumer)0
0xb400007241f94c90 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar1]#3(BLAST Consumer)3
0xb400007241f95a50 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar1]#3(BLAST Consumer)3
0xb400007241f95d10 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar1]#3(BLAST Consumer)3
0xb400007241f971b0 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar1]#3(BLAST Consumer)3
0xb400007241f980d0 | 760.00 KiB | 1280 (1280) x 152 | 1 | 1 | 0x b00 | VRI[StatusBar1]#3(BLAST Consumer)3
Total allocated by GraphicBufferAllocator (estimate): 85716.75 KB
Imported gralloc buffers:
+ name:VRI[DynamicIslandWindow]#10(BLAST Consumer)10, id:4793183516421, size:894.00KiB, w/h:1280x164, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:passBlur-24893, id:4793183516420, size:196.00KiB, w/h:320x41, usage: 0x10000300, req fmt:1, fourcc/mod:875708993/576460752303424337, dataspace: 0x8810000, compressed: true
+ name:passBlur-24893, id:4793183516419, size:196.00KiB, w/h:320x41, usage: 0x10000300, req fmt:1, fourcc/mod:875708993/576460752303424337, dataspace: 0x8810000, compressed: true
+ name:passBlur-24893, id:4793183516416, size:1172.00KiB, w/h:320x693, usage: 0x10000300, req fmt:1, fourcc/mod:875708993/576460752303424337, dataspace: 0x8810000, compressed: true
+ name:VRI[NotificationShade]#11(BLAST Consumer)11, id:4793183516415, size:14138.00KiB, w/h:1280x2772, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[NotificationShade]#11(BLAST Consumer)11, id:4793183516413, size:14138.00KiB, w/h:1280x2772, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[NotificationShade]#11(BLAST Consumer)11, id:4793183516412, size:14138.00KiB, w/h:1280x2772, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[NotificationShade]#11(BLAST Consumer)11, id:4793183516411, size:14138.00KiB, w/h:1280x2772, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[DynamicIslandWindow]#10(BLAST Consumer)10, id:4793183516407, size:894.00KiB, w/h:1280x164, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[DynamicIslandWindow]#10(BLAST Consumer)10, id:4793183516406, size:894.00KiB, w/h:1280x164, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[DynamicIslandWindow]#10(BLAST Consumer)10, id:4793183516410, size:894.00KiB, w/h:1280x164, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9, id:4793183516396, size:29.00KiB, w/h:448x13, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9, id:4793183516394, size:29.00KiB, w/h:448x13, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[NotificationShade]#11(BLAST Consumer)11, id:4793183516414, size:14138.00KiB, w/h:1280x2772, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[DynamicIslandWindow]#10(BLAST Consumer)10, id:4793183516409, size:894.00KiB, w/h:1280x164, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9, id:4793183516393, size:29.00KiB, w/h:448x13, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9, id:4793183516392, size:29.00KiB, w/h:448x13, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:passBlur-24893, id:4793183516408, size:196.00KiB, w/h:320x41, usage: 0x10000300, req fmt:1, fourcc/mod:875708993/576460752303424337, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar]#1(BLAST Consumer)1, id:4793183516184, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar1]#3(BLAST Consumer)3, id:4793183516195, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar]#1(BLAST Consumer)1, id:4793183516183, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar1]#3(BLAST Consumer)3, id:4793183516192, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:passBlur-24893, id:4793183516417, size:1172.00KiB, w/h:320x693, usage: 0x10000300, req fmt:1, fourcc/mod:875708993/576460752303424337, dataspace: 0x8810000, compressed: true
+ name:VRI[NavigationBar0]#0(BLAST Consumer)0, id:4793183516178, size:325.00KiB, w/h:1280x52, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar]#1(BLAST Consumer)1, id:4793183516185, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar1]#3(BLAST Consumer)3, id:4793183516191, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[Miui Bottom Caption of Task=1]#9(BLAST Consumer)9, id:4793183516395, size:29.00KiB, w/h:448x13, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[NavigationBar0]#0(BLAST Consumer)0, id:4793183516176, size:325.00KiB, w/h:1280x52, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar]#1(BLAST Consumer)1, id:4793183516181, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar]#1(BLAST Consumer)1, id:4793183516182, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar1]#3(BLAST Consumer)3, id:4793183516194, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:passBlur-24893, id:4793183516418, size:1172.00KiB, w/h:320x693, usage: 0x10000300, req fmt:1, fourcc/mod:875708993/576460752303424337, dataspace: 0x8810000, compressed: true
+ name:VRI[StatusBar1]#3(BLAST Consumer)3, id:4793183516193, size:813.00KiB, w/h:1280x152, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[NavigationBar0]#0(BLAST Consumer)0, id:4793183516180, size:325.00KiB, w/h:1280x52, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[NavigationBar0]#0(BLAST Consumer)0, id:4793183516179, size:325.00KiB, w/h:1280x52, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
+ name:VRI[NavigationBar0]#0(BLAST Consumer)0, id:4793183516177, size:325.00KiB, w/h:1280x52, usage: 0xb00, req fmt:1, fourcc/mod:875708993/576460752303423602, dataspace: 0x8810000, compressed: true
Total imported by gralloc: 89164.00KiB
| 属性名 | 解释 |
|---|---|
| Pipeline | 渲染管线的实现,使用 Vulkan 作为图形 API |
| Max surface area | 最大表面面积 |
| Max resource usage | 最大资源使用量 |
| Background retention | 后台保留策略 |
| IsSystemOrPersistent | 应用是是系统或持久性应用 |
| GPU Context timeout | GPU 上下文超时时间 |
| Glyph Cache | 字形缓存 |
| Glyph Count | 字形计数 |
| Total CPU memory usage | CPU 内存使用总量 ⇒ skia侧统计 |
| Image | 图像缓存 |
| Scratch | 临时缓存 |
| Surface | |
| GrVkTextureRenderTarget | 提供了一个可以同时用作纹理和渲染目标的资源 |
| Buffer Object | 用于存储线性数据,如顶点数据、索引数据、uniform 数据等 |
| GrVkImage | 用于存储多维数据,如纹理、帧缓冲等 |
| Total GPU memory usage | GPU 内存使用总量 ⇒ skia侧统计 |
| GraphicBufferAllocator buffers | 业务surface申请的buffer,机型不同,surface对应的buffer具体数量也有差异 |
| Imported gralloc buffers | 图形缓冲区(gralloc buffers)的详细信息 |
Hprof
Hprof(Heap Profiling)是堆内存快照,通过Hprof文件,可以量化当前系统内存使用情况,因此可以用于分析处理内存泄漏等场景。 Hprof在Android Studio 中可以直接打开并列出类、类的实例和实例的引用树,以此来跟踪内存的使用情况,找出内存泄漏的地方。 对于layer泄漏问题来说,Hprof文件非常关键!!!
- adb抓取hprof
adb shell 'am dumpheap `pidof com.android.systemui`'- 代码中dump
android.os.Debug.dumpHprofData("/data/anr/system_server_memory_leak_" + System.currentTimeMillis() + ".hprof");如现在我们在源码中封装的
//miui/frameworks/base/core/java/miui/mqsas/sdk/MiuiHprofCrop.java
public static synchronized void dumpHprofData(String fileName, boolean isGzip) throws IOException {
nOpenProxy(fileName, isGzip);
Debug.dumpHprofData(fileName);
nCloseProxy();
}- hprof打开方式
bugreport中的hprof文件一般在FS/data/miuilog/stability/resleak/layersleak/hprof目录下面,可以先看system_server的hprof文件。
hprof文件的打开方式有多种,直接将文件拖拽到AS中即可打开,可以解析之后使用MAT打开
- 使用Android Studio打开

| 名称 | 描述 |
|---|---|
| Class name | 类名 |
| Allocations | 这个类的分配的实例总数 |
| Native Size | 从 C 或 C++ 代码分配的对象的内存 |
| Shallow Size | 所选实例的大小,计算对象自身的内存占用情况,不考虑对象引用的其他对象所占用的内存空间 Shallow Size = [类定义] + 父类fields所占空间 + 自身fields所占空间 + [alignment] |
| Retained Size | 实例A的Retained Size是指, 当实例A被回收时, 可以同时被回收的实例的Shallow Size之和 比如某个 Bitmap实例的Retained Size很小, 证明它内部的byte数组被复用了, 有另一个Bitmap实例指向了同一个byte数组 |
| Instance | 具体的实例 |
| Reference | 所选实例的引用,以及指向该引用的引用⇒可以查看引用链 |
| Depth | GC根节点到所选实例的最短路径的深度 |
- 使用MAT打开
使用platform-tools中的工具转换后在MAT进行内存相关的diff,比较直观可以看出内存大小和对象数量的差异
./hprof-conv hprofData/bg_com.android.systemui-3.hprof bg_standard_3.hprof
Native Heap Insight
堆内存检视方案(Native Heap Insight)Systemui的native泄漏进展计划以及澄清文档
堆内存检视方案,用于分析和报告运行时堆内存使用情况,用于拆分Native heap内存申请情况
-
使用步骤:
-
需要userroot或者userdebug的包;
-
通过如下命令,之后便可使用Native Heap Insight:
adb root adb remount adb shell setprop persist.track.malloc.enable track-heap adb shell setprop persist.track.malloc.program com.android.systemui adb shell stop adb shell start -
对需要测试的场景进行操作,操作一段时间结束后通过如下命令获取相关日志:
adb shell 'kill -51 pidof com.android.systemui'- 查看日志,该日志将Native排名前十的堆栈进行打印,通过查看堆栈发现Native异常分配内存的情况;
-

- 解题实战:
https://jira-phone.mioffice.cn/browse/BUGOS2-336752
问题场景下泄漏的对象为 SkTypeface
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: Total size is 723307822 bytes, and here gives Top-10 stacks: // systemui总共占用723307822
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: -> stack key "2410eb862714708e"
: ref. 2262, size 538790304, 18358s, sampled at 2025-02-26 23:05:17 // SkTypeface堆栈调用2262次,大小538790304
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #00 pc 0000000000045618 /apex/com.android.runtime/lib64/bionic/libc.so (malloc+76)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #01 pc 000000000034ae60 /system/lib64/libhwui.so (sk_malloc_flags(unsigned long, unsigned int)+40)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #02 pc 0000000000039364 /system/lib64/libft2.so (ft_mem_qrealloc+164)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #03 pc 000000000008048c /system/lib64/libft2.so (tt_set_mm_blend+1328)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #04 pc 000000000007ee00 /system/lib64/libft2.so (TT_Set_Var_Design+532)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #05 pc 0000000000043448 /system/lib64/libft2.so (FT_Set_Var_Design_Coordinates+180)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #06 pc 00000000002eecb4 /system/lib64/libhwui.so (SkTypeface_FreeType::getFaceRec() const+380)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #07 pc 00000000002eeabc /system/lib64/libhwui.so (AutoFTAccess::AutoFTAccess(SkTypeface_FreeType const*)+72)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #08 pc 0000000000535b90 /system/lib64/libhwui.so (SkTypeface_FreeType::onGetTableData(unsigned int, unsigned long, unsigned long, void*) const+64)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #09 pc 000000000029a100 /system/lib64/libhwui.so (SkTypeface_FreeType::onGlyphMaskNeedsCurrentColor() const::$0::operator()() const (._uniq.323675718633992985652658630537108723239)+44)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #10 pc 000000000029a0a8 /system/lib64/libhwui.so (void SkOnce::operator()<SkTypeface_FreeType::onGlyphMaskNeedsCurrentColor() const::$0>(SkTypeface_FreeType::onGlyphMaskNeedsCurrentColor() const::$_0&&) (._uniq.323675718633992985652658630537108723239)+52)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #11 pc 0000000000522ed0 /system/lib64/libhwui.so (SkTypeface_FreeType::onGlyphMaskNeedsCurrentColor() const+40)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #12 pc 000000000028fc38 /system/lib64/libhwui.so (SkStrikeSpec::SkStrikeSpec(SkFont const&, SkPaint const&, SkSurfaceProps const&, SkScalerContextFlags, SkMatrix const&)+268)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #13 pc 0000000000270b78 /system/lib64/libhwui.so (android::PaintGlue::getMetricsInternal(long, SkFontMetrics*, bool) (.__uniq.295321301672566532533700490907482056561)+492)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #14 pc 000000000053e910 /system/lib64/libhwui.so (android::PaintGlue::getFontMetricsInt(JNIEnv*, _jobject*, long, _jobject*, unsigned char) (._uniq.295321301672566532533700490907482056561)+68)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #15 pc 00000000001f6a58 /system/framework/arm64/boot-framework.oat (art_jni_trampoline+104)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #16 pc 00000000005cae9c /system/framework/arm64/boot-framework.oat (android.text.TextLine.expandMetricsFromPaint+108)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #17 pc 0000000000792304 /apex/com.android.art/lib64/libart.so (nterp_helper+148)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #18 pc 00000000004b13b8 /system/framework/framework.jar (offset 0x11ff000)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #19 pc 00000000007938c4 /apex/com.android.art/lib64/libart.so (nterp_helper+5716)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #20 pc 00000000004b0d30 /system/framework/framework.jar (offset 0x11ff000)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #21 pc 00000000007938c4 /apex/com.android.art/lib64/libart.so (nterp_helper+5716)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #22 pc 00000000004b1c28 /system/framework/framework.jar (offset 0x11ff000)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #23 pc 0000000000cdea10 [anon_shmem:dalvik-jit-code-cache] (offset 0x2000000) (android.text.TextLine.measure+640)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #24 pc 0000000000793f98 /apex/com.android.art/lib64/libart.so (nterp_helper+7464)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #25 pc 00000000004b1cf0 /system/framework/framework.jar (offset 0x11ff000)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #26 pc 00000000007931c0 /apex/com.android.art/lib64/libart.so (nterp_helper+3920)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #27 pc 0000000000499510 /system/framework/framework.jar (offset 0x11ff000)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #28 pc 000000000081a924 /system/framework/arm64/boot-framework.oat (android.widget.TextView.onMeasure+532)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #29 pc 000000000075309c /system/framework/arm64/boot-framework.oat (android.view.View.measure+1916)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #30 pc 00000000007e3b0c /system/framework/arm64/boot-framework.oat (android.view.ViewGroup.measureChildWithMargins+252)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #31 pc 0000000000843f78 /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.measureChildBeforeLayout+56)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #32 pc 0000000000844548 /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.measureHorizontal+1448)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #33 pc 0000000000846d08 /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.onMeasure+72)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #34 pc 000000000075309c /system/framework/arm64/boot-framework.oat (android.view.View.measure+1916)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #35 pc 00000000007e3b0c /system/framework/arm64/boot-framework.oat (android.view.ViewGroup.measureChildWithMargins+252)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #36 pc 000000000083eb9c /system/framework/arm64/boot-framework.oat (android.widget.FrameLayout.onMeasure+348)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #37 pc 00000000003976dc [anon_shmem:dalvik-jit-code-cache] (offset 0x2000000) (com.android.systemui.statusbar.views.LimitedSizeFrameLayout.onMeasure+76)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #38 pc 000000000075309c /system/framework/arm64/boot-framework.oat (android.view.View.measure+1916)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #39 pc 00000000007e3b0c /system/framework/arm64/boot-framework.oat (android.view.ViewGroup.measureChildWithMargins+252)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #40 pc 000000000083eb9c /system/framework/arm64/boot-framework.oat (android.widget.FrameLayout.onMeasure+348)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #41 pc 000000000075309c /system/framework/arm64/boot-framework.oat (android.view.View.measure+1916)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #42 pc 00000000007e3b0c /system/framework/arm64/boot-framework.oat (android.view.ViewGroup.measureChildWithMargins+252)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #43 pc 0000000000843f78 /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.measureChildBeforeLayout+56)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #44 pc 0000000000844548 /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.measureHorizontal+1448)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #45 pc 0000000000846d08 /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.onMeasure+72)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #46 pc 000000000075309c /system/framework/arm64/boot-framework.oat (android.view.View.measure+1916)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #47 pc 00000000007e3b0c /system/framework/arm64/boot-framework.oat (android.view.ViewGroup.measureChildWithMargins+252)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #48 pc 0000000000843f78 /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.measureChildBeforeLayout+56)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #49 pc 0000000000845ee4 /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.measureVertical+884)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #50 pc 0000000000846cec /system/framework/arm64/boot-framework.oat (android.widget.LinearLayout.onMeasure+44)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #51 pc 000000000075309c /system/framework/arm64/boot-framework.oat (android.view.View.measure+1916)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #52 pc 00000000007e3b0c /system/framework/arm64/boot-framework.oat (android.view.ViewGroup.measureChildWithMargins+252)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #53 pc 000000000083eb9c /system/framework/arm64/boot-framework.oat (android.widget.FrameLayout.onMeasure+348)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #54 pc 000000000075309c /system/framework/arm64/boot-framework.oat (android.view.View.measure+1916)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #55 pc 0000000000d4eee4 [anon_shmem:dalvik-jit-code-cache] (offset 0x2000000) (androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure+2276)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #56 pc 000000000015574c [anon_shmem:dalvik-jit-code-cache] (offset 0x2000000) (androidx.constraintlayout.core.widgets.analyzer.DependencyGraph.measure+108)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #57 pc 0000000000cfb8ac [anon_shmem:dalvik-jit-code-cache] (offset 0x2000000) (androidx.constraintlayout.core.widgets.analyzer.DependencyGraph.basicMeasureWidgets+3612)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #58 pc 0000000000959aa8 [anon_shmem:dalvik-jit-code-cache] (offset 0x2000000) (androidx.constraintlayout.widget.ConstraintLayout.resolveSystem+3048)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #59 pc 0000000000c3cdb4 [anon_shmem:dalvik-jit-code-cache] (offset 0x2000000) (androidx.constraintlayout.widget.ConstraintLayout.onMeasure+3700)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #60 pc 0000000000396984 [anon_shmem:dalvik-jit-code-cache] (offset 0x2000000) (com.android.systemui.shade.MiuiNQSContainer.onMeasure+36)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #61 pc 000000000075309c /system/framework/arm64/boot-framework.oat (android.view.View.measure+1916)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #62 pc 00000000007e3b0c /system/framework/arm64/boot-framework.oat (android.view.ViewGroup.measureChildWithMargins+252)
02-26 23:05:21.593 1000 3335 3409 I INJECT track-heap: #63 pc 000000000083eb9c /system/framework/arm64/boot-framework.oat (android.widget.FrameLayout.onMeasure+348)- SkTypeface是Skia库中的一个类,用于处理字体相关的功能。
- TextView.onMeasure() 时,需要使用 skia中的 SkTypeface 进行文字测量,skia中使用StrikeCache进行SkTypeface的复用管理,一般情况下 SkTypeface 的数量不会太大。
- 问题场景下 SkTypeface 未复用,生成了大量新的 SkTypeface 对象,原因是业务侧一直在新建TextView,并且设置了 FontVariationSettings属性 (例如 ‘wght’)。
解决方案:

找到使用remoteview的业务并在需要频繁对TextView.onMeasure()场景取消fontVariationSettings的设置
Heap_Profile
谷歌提供dump 内存申请堆栈信息的工具,对于dump native信息非常实用
使用下面命令开始抓取trace文件
heap_profile -c 间隔时间 -n 包名
例如每100ms抓取一次systemui的内存: ./heap_profile -c 100 -n com.android.systemui

通过申请native内存的堆栈排查native内存堆积的原因
- 解题实战:
https://jira-phone.mioffice.cn/browse/BUGOS2-618194
bitmap堆积,所有的hprof抓取的bitmap已经释放,看raw-trace,通过getIconDescriptor方法创建的bitmap就有2G




解决方案:
copy一个不可变的bitmap

Smaps
抓取方式:
拿到systemui的进程号,后续需要用到,每个手机不一样
adb shell ps -A | grep com.android.systemui
adb shell cat /proc/pid/smaps > systemui_smaps.txt
通过 https://github.com/Gracker/Android-App-Memory-Analysis 提供的脚本拆分 smaps文件:
python3 smaps_parser.py -f smaps >smaps_parser.txt
python3 smaps_parser.py -f ./data/smaps3 > ./data/smaps_parser3.txt可以得到比meminfo更详细的内存信息:
- 解题实战:
systemui开机内存超标
https://jira-phone.mioffice.cn/browse/BUGOS2-594816

开机后没有使用ScreenRecorder,但是在systemui的内存中却mmap了ScreenRecorder的apk
解决方案:
- 判断完是否支持展示后就destroy掉,且不将tile添加在集合中,后续只有被添加在控制中心里后才去创建tile

Mem_profile
mem_profile是用于mail 平台获取GPU相关内存信息,所以cat这个信息主要用于分析Mtk/Xring平台的GL mtrack内存信息,如果需要更进阶的分析graphics的方法,可以参考这篇文档Graphics内存数据拆解
Mtk平台直接执行如下命令
cat /sys/kernel/debug/mali0/ctx/$(pidof com.android.systemui)_*/mem_profile
adb shell 'cat /sys/kernel/debug/mali0/ctx/$(pidof com.android.systemui)_*/mem_profile'Xring平台,需要
如果出现/sys/kernel/debug下无内容得情况,则需要先执行:adb shell mount -t debugfs none /sys/kernel/debug
cat mem_profile之前需要先执行如下命令:
adb shell setprop vendor.mali.xfeature_mem_usage_report 1
adb shell stop
adb shell start
通过mem_profile可以获取GFX Device Memory CPU Uncached、Vulkan Bound Buffer Memory、Vulkan Bound Image Memory通道相关的GPU内存信息,这些内存主要通过vkAllocateMemory api申请。